TN068: esecuzione di transazioni con il driver ODBC di Microsoft Access 7

Nota

La seguente nota tecnica non è stata aggiornata da quando è stata inclusa per la prima volta nella documentazione online. Di conseguenza, alcune procedure e argomenti potrebbero essere non aggiornati o errati. Per le informazioni più recenti, è consigliabile cercare l'argomento di interesse nell'indice della documentazione online.

Questa nota descrive come eseguire transazioni quando si usano le classi di database ODBC MFC e il driver ODBC di Microsoft Access 7.0 incluso in Microsoft ODBC Desktop Driver Pack versione 3.0.

Panoramica

Se l'applicazione di database esegue transazioni, è necessario prestare attenzione a chiamare CDatabase::BeginTrans e CRecordset::Open nella sequenza corretta nell'applicazione. Il driver di Microsoft Access 7.0 usa il motore di database Microsoft Jet e Jet richiede che l'applicazione non inizi una transazione su qualsiasi database con un cursore aperto. Per le classi di database ODBC MFC, un cursore aperto equivale a un oggetto aperto CRecordset .

Se si apre un recordset prima di chiamare BeginTrans, è possibile che non vengano visualizzati messaggi di errore. Tuttavia, tutti gli aggiornamenti del recordset apportati dall'applicazione diventano permanenti dopo la chiamata CRecordset::Updatea e non verrà eseguito il rollback degli aggiornamenti chiamando Rollback. Per evitare questo problema, è necessario chiamare BeginTrans prima e quindi aprire il recordset.

MFC controlla la funzionalità del driver per il commit del cursore e il comportamento di rollback. La classe CDatabase fornisce due funzioni membro e GetCursorRollbackBehaviorGetCursorCommitBehavior , per determinare l'effetto di qualsiasi transazione sull'oggetto apertoCRecordset. Per il driver ODBC di Microsoft Access 7.0, queste funzioni membro restituiscono SQL_CB_CLOSE perché il driver di Access non supporta la conservazione dei cursori. Pertanto, è necessario chiamare CRecordset::Requery dopo un'operazione CommitTrans o Rollback .

Quando è necessario eseguire più transazioni una dopo l'altra, non è possibile chiamare Requery dopo la prima transazione e quindi avviare quella successiva. È necessario chiudere il recordset prima della chiamata successiva a BeginTrans per soddisfare i requisiti di Jet. Questa nota tecnica descrive due metodi di gestione di questa situazione:

  • Chiusura del recordset dopo ogni CommitTrans operazione o Rollback .

  • Uso della funzione SQLFreeStmtAPI ODBC .

Chiusura dell'oggetto Recordset dopo ogni operazione committrans o rollback

Prima di avviare una transazione, assicurarsi che l'oggetto recordset sia chiuso. Dopo aver chiamato , chiamare BeginTransla funzione membro del Open recordset. Chiudere il recordset immediatamente dopo aver chiamato CommitTrans o Rollback. Si noti che l'apertura e la chiusura ripetute del recordset possono rallentare le prestazioni di un'applicazione.

Uso di SQLFreeStmt

È anche possibile usare la funzione SQLFreeStmt API ODBC per chiudere in modo esplicito il cursore dopo aver terminato una transazione. Per avviare un'altra transazione, chiamare BeginTrans seguito da CRecordset::Requery. Quando si chiama SQLFreeStmt, è necessario specificare HSTMT del recordset come primo parametro e SQL_CLOedizione Standard come secondo parametro. Questo metodo è più veloce rispetto alla chiusura e all'apertura del recordset all'inizio di ogni transazione. Il codice seguente illustra 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 consiste nel scrivere una nuova funzione, RequeryWithBeginTrans, che è possibile chiamare per avviare la transazione successiva dopo il commit o il rollback della prima. Per scrivere una funzione di questo tipo, seguire questa procedura:

  1. Copiare il codice per CRecordset::Requery( ) nella nuova funzione.

  2. Aggiungere la riga seguente subito dopo la chiamata a SQLFreeStmt:

    m_pDatabase->BeginTrans( );

È ora possibile chiamare questa funzione tra ogni coppia di 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 usare questa tecnica se è necessario modificare le variabili membro del recordset m_strFilter o m_strSort tra transazioni. In tal caso, è necessario chiudere il recordset dopo ogni CommitTrans operazione o Rollback .

Vedi anche

Note tecniche per numero
Note tecniche per categoria