TN068: realizando transações com o driver ODBC do Microsoft Access 7
Observação
A nota técnica a seguir não foi atualizada desde que foi incluída pela primeira vez na documentação online. Como resultado, alguns procedimentos e tópicos podem estar desatualizados ou incorretos. Para obter as informações mais recentes, é recomendável que você pesquise o tópico de interesse no índice de documentação online.
Esta nota descreve como executar transações ao usar as classes de banco de dados ODBC do MFC e o driver ODBC do Microsoft Access 7.0 incluído no Microsoft ODBC Desktop Driver Pack versão 3.0.
Visão geral
Se o seu aplicativo de banco de dados executar transações, você deverá ter cuidado ao chamar CDatabase::BeginTrans
e CRecordset::Open
na sequência correta em seu aplicativo. O driver do Microsoft Access 7.0 usa o mecanismo de banco de dados do Microsoft Jet, e o Jet exige que o seu aplicativo não inicie uma transação em qualquer banco de dados que tenha cursor aberto. Para as classes de banco de dados ODBC do MFC, um cursor aberto equivale a um objetoCRecordset
aberto.
Se você abrir um conjunto de registros antes de chamar BeginTrans
, talvez não veja nenhuma mensagem de erro. No entanto, qualquer atualização de conjunto de registros que seu aplicativo fizer se torna permanente após chamar CRecordset::Update
, e as atualizações não serão revertidas chamando Rollback
. Para evitar esse problema, você deve chamar BeginTrans
primeiro e só depois abrir o conjunto de registros.
O MFC verifica a funcionalidade do driver quanto ao comportamento para fazer commit e reverter o cursor. A classe CDatabase
fornece duas funções membro, GetCursorCommitBehavior
e GetCursorRollbackBehavior
, para determinar o efeito de qualquer transação em seu objeto CRecordset
aberto. Para o driver ODBC do Microsoft Access 7.0, essas funções de membro retornam SQL_CB_CLOSE
porque o driver do Access não dá suporte à preservação do cursor. Por conta disso, você precisa chamar CRecordset::Requery
após uma operação CommitTrans
ou Rollback
.
Quando você precisa executar várias transações uma após a outra, não é possível chamar Requery
após a primeira transação e, em seguida, iniciar a próxima. Você deve fechar o conjunto de registros antes da próxima chamada para BeginTrans
para atender aos requisitos do Jet. Esta nota técnica descreve dois métodos para lidar com essa situação:
Fechar o conjunto de registros após cada operação
CommitTrans
ouRollback
.Usar a função de API ODBC
SQLFreeStmt
.
Fechar o conjunto de registros após cada operação CommitTrans ou Rollback
Antes de iniciar uma transação, verifique se o objeto do conjunto de registros está fechado. Depois de chamar BeginTrans
, chame a função membro Open
do conjunto de registros. Feche o conjunto de registros imediatamente após chamar CommitTrans
ou Rollback
. Observe que abrir e fechar o conjunto de registros repetidamente pode diminuir o desempenho de um aplicativo.
Usar SQLFreeStmt
Você também pode usar a função de API ODBC SQLFreeStmt
para fechar explicitamente o cursor depois de encerrar uma transação. Para iniciar outra transação, chame BeginTrans
seguido por CRecordset::Requery
. Ao chamar SQLFreeStmt
, você deve especificar o HSTMT do conjunto de registros como o primeiro parâmetro, e SQL_CLOSE como o segundo parâmetro. Esse método é mais rápido do que fechar e abrir o conjunto de registros no início de cada transação. O exemplo de código a seguir demonstra como implementar essa 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();
Outra maneira de implementar essa técnica é escrever uma nova função, RequeryWithBeginTrans
, que você pode chamar para iniciar a próxima transação depois de confirmar ou reverter a primeira. Para escrever essa função, siga estas etapas:
Copie o código de
CRecordset::Requery( )
para a nova função.Adicione a seguinte linha imediatamente após a chamada para
SQLFreeStmt
:m_pDatabase->BeginTrans( );
Agora você pode chamar essa função entre cada par de transações:
// 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()
Observação
Não use essa técnica se precisar alterar as variáveis de membro do conjunto de registros m_strFilter ou m_strSort entre transações. Nesse caso, você deve fechar o conjunto de registros após cada operação CommitTrans
ou Rollback
.
Confira também
Observações técnicas por número
Observações técnicas por categoria