TN068: Realizar transacciones con el controlador ODBC de Microsoft Access 7TN068: Performing Transactions with the Microsoft Access 7 ODBC Driver

Nota

La nota técnica siguiente no se ha actualizado desde que se incluyó por primera vez en la documentación en línea.The following technical note has not been updated since it was first included in the online documentation. Como resultado, algunos procedimientos y temas podrían estar obsoletos o ser incorrectos.As a result, some procedures and topics might be out of date or incorrect. Para obtener información más reciente, se recomienda buscar el tema de interés en el índice de la documentación en línea.For the latest information, it is recommended that you search for the topic of interest in the online documentation index.

Esta nota describe cómo realizar las transacciones cuando se usan las clases de base de datos ODBC de MFC y el controlador ODBC de Microsoft Access 7.0 incluidas en la versión de escritorio de Microsoft ODBC Driver Pack 3.0.This note describes how to perform transactions when using the MFC ODBC database classes and the Microsoft Access 7.0 ODBC driver included in the Microsoft ODBC Desktop Driver Pack version 3.0.

Información generalOverview

Si la aplicación de base de datos realiza las transacciones, debe llamar a CDatabase::BeginTrans y CRecordset::Open en la secuencia correcta en la aplicación.If your database application performs transactions, you must be careful to call CDatabase::BeginTrans and CRecordset::Open in the correct sequence in your application. El controlador de Microsoft Access 7.0 utiliza el motor de base de datos Microsoft Jet y Jet requiere que la aplicación no iniciar una transacción en cualquier base de datos con un cursor abierto.The Microsoft Access 7.0 driver uses the Microsoft Jet database engine, and Jet requires that your application not begin a transaction on any database that has an open cursor. Para las clases de base de datos ODBC de MFC, un cursor abierto equivale a una apertura CRecordset objeto.For the MFC ODBC database classes, an open cursor equates to an open CRecordset object.

Si abre un conjunto de registros antes de llamar a BeginTrans, no puede ver los mensajes de error.If you open a recordset before calling BeginTrans, you may not see any error messages. Sin embargo, cualquier conjunto de registros actualiza su aplicación tiene que convertirse en permanente después de llamar a CRecordset::Update, y las actualizaciones no se revertirán mediante una llamada a Rollback.However, any recordset updates your application makes become permanent after calling CRecordset::Update, and the updates will not be rolled back by calling Rollback. Para evitar este problema, debe llamar a BeginTrans primero y, a continuación, abra el conjunto de registros.To avoid this problem, you must call BeginTrans first and then open the recordset.

MFC comprueba la funcionalidad del controlador para el comportamiento del cursor commit y rollback.MFC checks the driver functionality for cursor commit and rollback behavior. Clase CDatabase proporciona dos funciones miembro, GetCursorCommitBehavior y GetCursorRollbackBehavior, para determinar el efecto de cualquier transacción en el abierto CRecordset objeto.Class CDatabase provides two member functions, GetCursorCommitBehavior and GetCursorRollbackBehavior, to determine the effect of any transaction on your open CRecordset object. Para el controlador ODBC de Microsoft Access 7.0, estas funciones miembro devuelven SQL_CB_CLOSE porque el controlador de Access no admite la conservación del cursor.For the Microsoft Access 7.0 ODBC driver, these member functions return SQL_CB_CLOSE because the Access driver does not support cursor preservation. Por lo tanto, debe llamar a CRecordset::Requery siguiente un CommitTrans o Rollback operación.Therefore, you must call CRecordset::Requery following a CommitTrans or Rollback operation.

Cuando deba realizar varias transacciones uno tras otro, no puede llamar a Requery después de la primera transacción y después iniciar siguiente.When you need to perform multiple transactions one after another, you cannot call Requery after the first transaction and then start the next one. Debe cerrar el conjunto de registros antes de la siguiente llamada a BeginTrans con el fin de satisfacer el requisito de Jet.You must close the recordset before the next call to BeginTrans in order to satisfy Jet's requirement. Esta nota técnica describe dos métodos para controlar esta situación:This technical note describes two methods of handling this situation:

  • Cierre el conjunto de registros después de cada CommitTrans o Rollback operación.Closing the recordset after each CommitTrans or Rollback operation.

  • Mediante la función de la API de ODBC SQLFreeStmt.Using the ODBC API function SQLFreeStmt.

Cierre el conjunto de registros después de cada operación de reversión o CommitTransClosing the Recordset after each CommitTrans or Rollback Operation

Antes de iniciar una transacción, asegúrese de que el objeto de conjunto de registros está cerrado.Before starting a transaction, make sure the recordset object is closed. Después de llamar a BeginTrans, llame a la función miembro Open función miembro.After calling BeginTrans, call the recordset's Open member function. Cierre el conjunto de registros inmediatamente después de llamar a CommitTrans o Rollback.Close the recordset immediately after calling CommitTrans or Rollback. Tenga en cuenta que varias veces de apertura y cierre el conjunto de registros pueden ralentizar el rendimiento de la aplicación.Note that repeatedly opening and closing the recordset can slow an application's performance.

Using SQLFreeStmtUsing SQLFreeStmt

También puede usar la función de la API de ODBC SQLFreeStmt cerrar explícitamente el cursor después de finalizar una transacción.You can also use the ODBC API function SQLFreeStmt to explicitly close the cursor after ending a transaction. Para iniciar otra transacción, llame a BeginTrans seguido CRecordset::Requery.To start another transaction, call BeginTrans followed by CRecordset::Requery. Al llamar a SQLFreeStmt, debe especificar HSTMT del conjunto de registros como primer parámetro y SQL_CLOSE como segundo parámetro.When calling SQLFreeStmt, you must specify the recordset's HSTMT as the first parameter and SQL_CLOSE as the second parameter. Este método es más rápido que el conjunto de registros al principio de cada transacción de apertura y cierre.This method is faster than closing and opening the recordset at the start of every transaction. El código siguiente muestra cómo implementar esta técnica:The following code demonstrates how to implement this 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();

Otra manera de implementar esta técnica es escribir una nueva función, RequeryWithBeginTrans, que puede llamar para iniciar la siguiente transacción después de confirmar o revertir la primera de ellas.Another way to implement this technique is to write a new function, RequeryWithBeginTrans, which you can call to start the next transaction after you commit or rollback the first one. Para escribir una función de ese tipo, realice los pasos siguientes:To write such a function, do the following steps:

  1. Copie el código para CRecordset::Requery( ) a la nueva función.Copy the code for CRecordset::Requery( ) to the new function.

  2. Agregue la siguiente línea inmediatamente después de llamar a SQLFreeStmt:Add the following line immediately after the call to SQLFreeStmt:

    m_pDatabase->BeginTrans( );

Ahora puede llamar a esta función entre cada par de transacciones:Now you can call this function between each pair of 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()

Nota

No use esta técnica si tiene que cambiar las variables de miembro del conjunto de registros m_strFilter o m_strSort entre las transacciones.Do not use this technique if you need to change the recordset member variables m_strFilter or m_strSort between transactions. En ese caso, debe cerrar el conjunto de registros después de cada CommitTrans o Rollback operación.In that case, you should close the recordset after each CommitTrans or Rollback operation.

Vea tambiénSee also

Notas técnicas por númeroTechnical Notes by Number
Notas técnicas por categoríaTechnical Notes by Category