TN068: Eseguire transazioni con il driver ODBC di Microsoft Access 7
[!NOTA]
La seguente nota tecnica non è stata aggiornata dalla prima volta che viene inclusa nella documentazione online.Di conseguenza, alcune procedure e argomenti potrebbero non essere aggiornati o errati.Per le informazioni più recenti, è consigliabile cercare l'argomento di interesseindice della documentazione online.
Questa nota viene descritto come eseguire transazioni durante l'utilizzo delle classi di database ODBC MFC e il driver ODBC di Microsoft Access 7,0 inclusi nella versione desktop 3,0 del pacchetto del driver Microsoft ODBC.
Panoramica
Se l'applicazione di database non esegue le transazioni, è necessario prestare attenzione a chiamare CDatabase::BeginTrans e CRecordset::Open nella sequenza corretta nell'applicazione.Il driver per Microsoft Access 7,0 utilizza il modulo di gestione di database Microsoft Jet e jet richiede all'inizio dell'applicazione non una transazione in qualsiasi database che dispone di un cursore aperto.Per le classi di database ODBC MFC, un cursore aperto definitiva a CRecordset un oggetto aperto.
Se si apre un recordset prima di chiamare BeginTrans, non è possibile visualizzare alcuni messaggi di errore.Tuttavia, il recordset aggiorna l'applicazione è diventata permanente dopo aver chiamato CRecordset::Updatee gli aggiornamenti non verranno verrà eseguito il rollback di chiamando Rollback.Per evitare questo problema, è necessario chiamare BeginTrans innanzitutto quindi si apre il recordset.
MFC controlla la funzionalità del driver per il commit del cursore e il comportamento di rollback.La classe CDatabase vengono fornite due funzioni membro, GetCursorCommitBehavior e GetCursorRollbackBehavior, per determinare l'effetto di una transazione sull'oggetto aperto di CRecordset .Per il driver ODBC di Microsoft Access 7,0, queste funzioni membro restituiscono SQL_CB_CLOSE perché il driver di accesso non supporta la conservazione del cursore.Pertanto, è necessario chiamare CRecordset::Requery dopo un'operazione di Rollback o di CommitTrans .
Quando è necessario eseguire più transazioni uno dopo l'altro, non è possibile chiamare Requery dopo la prima transazione e quindi avviare il successivo.È necessario chiudere il recordset prima della chiamata successiva a BeginTrans per rispondere all'esigenza di jet.Questa nota tecnica descritti due metodi di gestire questa situazione:
Chiudere il recordset dopo ogni operazione di Rollback o di CommitTrans .
Utilizzando la funzione API ODBC SQLFreeStmt.
Chiudere il recordset dopo ogni operazione di rollback o di CommitTrans
Prima di avviare una transazione, assicurarsi che l'oggetto recordset sia chiuso.Dopo aver chiamato BeginTrans, chiamare la funzione membro di Apri del recordset.Chiudere il recordset immediatamente dopo il chiamare CommitTrans o Rollback.Si noti che ripetutamente aprire e chiudere il recordset possono rallentare le prestazioni di un'applicazione.
Utilizzando SQLFreeStmt
È inoltre possibile utilizzare la funzione API ODBC SQLFreeStmt in modo esplicito per chiudere il cursore dopo avere terminato una transazione.Per avviare un'altra transazione, la chiamata BeginTrans è seguito da CRecordset::Requery.Nel chiamare SQLFreeStmt, è necessario specificare il HSTMT del recordset come primo parametro e SQL_CLOSE come secondo parametro.Questo metodo è più veloce di chiusura e di apertura del recordset all'inizio di ogni transazione.Il codice seguente viene illustrato come implementare questa tecnica:
CMyDatabase db;
db.Open( "MYDATASOURCE" );
CMyRecordset rs( &db );
// start transaction 1 and
// open the recordset
db.BeginTrans( );
rs.Open( );
// manipulate data
// end transaction 1
db.CommitTrans( ); // or Rollback( )
// close the cursor
::SQLFreeStmt( rs.m_hstmt, SQL_CLOSE );
// start transaction 2
db.BeginTrans( );
// now get the result set
rs.Requery( );
// manipulate data
// end transaction 2
db.CommitTrans( );
rs.Close( );
db.Close( );
Un altro modo per implementare questa tecnica è scrivere una nuova funzione, RequeryWithBeginTrans, che è possibile chiamare per avviare la transazione seguente dopo aver eseguito il commit o il rollback la prima.Per scrivere tale funzione, eseguire i passaggi seguenti:
Copiare il codice per CRecordset::Requery( ) alla nuova funzione.
Aggiungere la riga seguente immediatamente dopo la chiamata a SQLFreeStmt:
m_pDatabase->BeginTrans( );
Ora è possibile chiamare la funzione tra ciascuna coppia delle transazioni:
// start transaction 1 and
// open the recordset
db.BeginTrans( );
rs.Open( );
// manipulate data
// end transaction 1
db.CommitTrans( ); // or Rollback( )
// close the cursor, start new transaction,
// and get the result set
rs.RequeryWithBeginTrans( );
// manipulate data
// end transaction 2
db.CommitTrans( ); // or Rollback( )
[!NOTA]
Non utilizzare questa tecnica se è necessario modificare le variabili membro m_strFilter o m_strSort di recordset tra le transazioni.In tal caso, è necessario chiudere il recordset dopo ogni operazione di Rollback o di CommitTrans .