TN068: Realizar transacciones con el controlador ODBC de Microsoft Access 7

Nota:

La nota técnica siguiente no se ha actualizado desde que se incluyó por primera vez en la documentación en línea. Como resultado, algunos procedimientos y temas podrían estar obsoletos o ser incorrectos. 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.

En esta nota se describe cómo realizar transacciones al usar las clases de base de datos de ODBC de MFC y el controlador ODBC de Microsoft Access 7.0 incluido en el paquete de controladores para Microsoft ODBC Desktop versión 3.0.

Información general

Si la aplicación de base de datos realiza transacciones, debe tener cuidado de llamar a CDatabase::BeginTrans y CRecordset::Open en la secuencia correcta de la aplicación. El controlador de Microsoft Access 7.0 usa el motor de base de datos de Microsoft Jet y Jet requiere que la aplicación no inicie una transacción en ninguna base de datos que tenga un cursor abierto. Para las clases de base de datos ODBC de MFC, un cursor abierto equivale a un objeto CRecordset abierto.

Si abre un conjunto de registros antes de llamar a BeginTrans, es posible que no vea ningún mensaje de error. Sin embargo, las actualizaciones del conjunto de registros que la aplicación realiza se convierten en permanentes después de llamar a CRecordset::Updatey las actualizaciones no se revertirán al llamar a Rollback. Para evitar este problema, primero debe llamar a BeginTrans y, a continuación, abrir el conjunto de registros.

MFC comprueba la funcionalidad del controlador para comprobar el comportamiento de reversión y confirmación del cursor. La clase CDatabase proporciona dos funciones miembro, GetCursorCommitBehavior y GetCursorRollbackBehavior, para determinar el efecto de cualquier transacción en el objeto CRecordset abierto. 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. Por lo tanto, debe llamar a CRecordset::Requery después de una operación CommitTrans o Rollback.

Cuando necesite realizar varias transacciones una después de otra, no puede llamar a Requery después de la primera transacción y, a continuación, iniciar la siguiente. Debe cerrar el conjunto de registros antes de la siguiente llamada a BeginTrans para satisfacer los requisitos de Jet. Esta nota técnica describe dos métodos para controlar esta situación:

  • Cerrar el conjunto de registros después de cada operación CommitTrans o Rollback.

  • Usar la función de API de ODBCSQLFreeStmt.

Cierre del conjunto de registros después de cada operación CommitTrans o Rollback

Antes de iniciar una transacción, asegúrese de que el objeto del conjunto de registros está cerrado. Después de llamar a BeginTrans, llame a la función miembro Open del conjunto de registros. Cierre el conjunto de registros inmediatamente después de llamar a CommitTrans o Rollback. Tenga en cuenta que abrir y cerrar repetidamente el conjunto de registros puede ralentizar el rendimiento de una aplicación.

Uso de SQLFreeStmt

También puede usar la función SQLFreeStmt de la API de ODBC para cerrar explícitamente el cursor después de finalizar una transacción. Para iniciar otra transacción, llame a BeginTrans seguida de CRecordset::Requery. Al llamar a SQLFreeStmt, debe especificar el HSTMT del conjunto de registros como primer parámetro y SQL_CLOSE como segundo parámetro. Este método es más rápido que cerrar y abrir el conjunto de registros al principio de cada transacción. El siguiente código muestra cómo implementar esta técnica:

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, a la que puede llamar para iniciar la siguiente transacción después de confirmar o revertir la primera. Para escribir esta función, siga estos pasos:

  1. Copie el código para CRecordset::Requery( ) en la nueva función.

  2. Agregue la siguiente línea inmediatamente después de la llamada a SQLFreeStmt:

    m_pDatabase->BeginTrans( );

Ahora puede llamar a esta función entre cada par de transacciones:

// 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 necesita cambiar las variables miembro del conjunto de registros m_strFilter o m_strSort entre transacciones. En ese caso, debe cerrar el conjunto de registros después de cada operaciónCommitTrans o Rollback.

Consulte también

Notas técnicas por número
Notas técnicas por categoría