TN068 : exécution de transactions avec le pilote ODBC Microsoft Access 7
Remarque
La note technique suivante n'a pas été mise à jour depuis son inclusion initiale dans la documentation en ligne. Par conséquent, certaines procédures et rubriques peuvent être obsolètes ou incorrectes. Pour obtenir les informations les plus récentes, il est recommandé de rechercher l'objet qui vous intéresse dans l'index de la documentation en ligne.
Cette remarque explique comment effectuer des transactions lors de l’utilisation des classes de base de données ODBC MFC et du pilote ODBC Microsoft Access 7.0 inclus dans le pack de pilotes Microsoft ODBC Desktop Version 3.0.
Vue d’ensemble
Si votre application de base de données effectue des transactions, vous devez être prudent pour appeler CDatabase::BeginTrans
et CRecordset::Open
dans la séquence appropriée dans votre application. Le pilote Microsoft Access 7.0 utilise le moteur de base de données Microsoft Jet, et Jet exige que votre application ne démarre pas de transaction sur une base de données qui a un curseur ouvert. Pour les classes de base de données ODBC MFC, un curseur ouvert équivaut à un objet ouvert CRecordset
.
Si vous ouvrez un jeu d’enregistrements avant d’appeler BeginTrans
, vous ne voyez peut-être aucun message d’erreur. Toutefois, les mises à jour du jeu d’enregistrements que votre application effectue deviennent permanentes après l’appel CRecordset::Update
et les mises à jour ne seront pas restaurées en appelant Rollback
. Pour éviter ce problème, vous devez d’abord appeler BeginTrans
, puis ouvrir le jeu d’enregistrements.
MFC case activée la fonctionnalité de pilote pour le comportement de validation et de restauration du curseur. La classe CDatabase
fournit deux fonctions membres etGetCursorRollbackBehavior
GetCursorCommitBehavior
, pour déterminer l’effet d’une transaction sur votre objet ouvertCRecordset
. Pour le pilote ODBC Microsoft Access 7.0, ces fonctions membres retournent SQL_CB_CLOSE
, car le pilote Access ne prend pas en charge la conservation des curseurs. Par conséquent, vous devez appeler CRecordset::Requery
à la suite d’une ou Rollback
d’une CommitTrans
opération.
Lorsque vous devez effectuer plusieurs transactions l’une après l’autre, vous ne pouvez pas appeler Requery
après la première transaction, puis démarrer la prochaine. Vous devez fermer le jeu d’enregistrements avant l’appel BeginTrans
suivant pour répondre aux besoins de Jet. Cette note technique décrit deux méthodes de gestion de cette situation :
Fermeture du jeu d’enregistrements après chaque
CommitTrans
ouRollback
opération.Utilisation de la fonction
SQLFreeStmt
API ODBC .
Fermeture du jeu d’enregistrements après chaque opération CommitTrans ou Rollback
Avant de démarrer une transaction, vérifiez que l’objet recordset est fermé. Après l’appel BeginTrans
, appelez la fonction membre du jeu d’enregistrements Open
. Fermez le jeu d’enregistrements immédiatement après l’appel CommitTrans
ou Rollback
. Notez que l’ouverture et la fermeture répétées du jeu d’enregistrements peuvent ralentir les performances d’une application.
Utilisation de SQLFreeStmt
Vous pouvez également utiliser la fonction SQLFreeStmt
API ODBC pour fermer explicitement le curseur après avoir terminé une transaction. Pour démarrer une autre transaction, appel BeginTrans
suivi de CRecordset::Requery
. Lors de l’appel SQLFreeStmt
, vous devez spécifier le HSTMT du jeu d’enregistrements comme premier paramètre et SQL_CLOSE comme deuxième paramètre. Cette méthode est plus rapide que la fermeture et l’ouverture du jeu d’enregistrements au début de chaque transaction. Le code suivant montre comment implémenter cette technique :
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();
Une autre façon d’implémenter cette technique consiste à écrire une nouvelle fonction, RequeryWithBeginTrans
que vous pouvez appeler pour démarrer la transaction suivante après la validation ou la restauration du premier. Pour écrire une telle fonction, procédez comme suit :
Copiez le code correspondant
CRecordset::Requery( )
à la nouvelle fonction.Ajoutez la ligne suivante immédiatement après l’appel à
SQLFreeStmt
:m_pDatabase->BeginTrans( );
Vous pouvez maintenant appeler cette fonction entre chaque paire de transactions :
// 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()
Remarque
N’utilisez pas cette technique si vous devez modifier les variables membres du jeu d’enregistrements m_strFilter ou m_strSort entre les transactions. Dans ce cas, vous devez fermer le jeu d’enregistrements après chaque CommitTrans
ou Rollback
opération.