TN068: wykonywanie transakcji za pomocą sterownika Microsoft Access 7 ODBC Driver
[!UWAGA]
Następująca uwaga techniczna nie został zaktualizowana od pierwszego uwzględnienia jej w dokumentacji online.W rezultacie niektóre procedury i tematy może być nieaktualne lub nieprawidłowe.Aby uzyskać najnowsze informacje, zaleca się wyszukać temat w indeksie dokumentacji online.
Uwaga ta opisuje sposób wykonać transakcji podczas korzystania z klasami baz danych MFC ODBC i sterownika ODBC programu Microsoft Access 7.0 w wersji Microsoft ODBC Desktop Driver Pack 3.0.
Omówienie
Jeśli transakcje są wykonywane w aplikacji bazy danych, należy zachować ostrożność, aby zadzwonić do CDatabase::BeginTrans i CRecordset::Open w poprawnej kolejności w aplikacji.Aparat bazy danych Microsoft Jet używa sterownika programu Microsoft Access w wersji 7.0 i aparatu Jet wymaga, że aplikacja nie rozpocząć transakcji na dowolnej bazy danych, która ma otwartego kursora.Dla klas bazy danych MFC ODBC, otwartego kursora jest równa otwarty CRecordset obiektu.
Jeśli otworzysz zestaw rekordów przed wywołaniem funkcji BeginTrans, mogą nie być widoczne wszystkie komunikaty o błędach.Jednak żadnych rekordów aktualizuje swoje aplikacji sprawia, że stają się stałe po wywołaniu CRecordset::Update, a aktualizacje będą nie można wycofać poprzez wywołanie Rollback.Aby uniknąć tego problemu, należy wywołać BeginTrans pierwszego, a następnie otwórz zestaw rekordów.
MFC sprawdza funkcjonalność sterownika dla zachowania kursor i wycofywania.Klasa CDatabase zapewnia dwie funkcje składowe, GetCursorCommitBehavior i GetCursorRollbackBehavior, aby określić efekt każdej transakcji na Twój Otwórz CRecordset obiektu.Dla sterownika Microsoft Access 7.0 ODBC funkcje Członkowskie zwracają SQL_CB_CLOSE , ponieważ sterownik programu Access nie obsługuje zachowania kursor.W związku z tym, należy wywołać CRecordset::Requery następujące CommitTrans lub Rollback operacji.
Gdy trzeba wykonać wiele transakcji, jeden po drugim, nie można wywołać funkcji Requery po pierwszej transakcji i Rozpocznij następny.Musisz zamknąć zestaw rekordów przed kolejnym wywołaniu BeginTrans w celu spełnienia wymogu Jet.Ta uwaga techniczna w tym artykule opisano dwie metody obsługi tej sytuacji:
Zamknięcie zestawu rekordów po każdym CommitTrans lub Rollback operacji.
Za pomocą funkcji interfejsu API ODBC SQLFreeStmt.
Zamknięcie zestawu rekordów po każdym CommitTrans lub operacji wycofywania
Przed rozpoczęciem transakcji, upewnij się, że obiekt recordset jest zamknięty.Po wywołaniu BeginTrans, wywołanie zestawu rekordów Otwórz funkcji składowej.Zamknij zestaw rekordów, natychmiast po wywołaniu CommitTrans lub Rollback.Należy zauważyć, że wielokrotne otwieranie i zamykanie zestaw rekordów może zmniejszyć wydajność aplikacji.
Przy użyciu SQLFreeStmt
Można również użyć funkcji interfejsu API ODBC SQLFreeStmt jawnego zamknięcia kursora po zakończeniu transakcji.Aby uruchomić kolejną transakcję, wywołanie BeginTrans następuje CRecordset::Requery.Podczas wywoływania SQLFreeStmt, należy określić HSTMT zestawu rekordów jako pierwszy parametr i SQL_CLOSE jako drugi parametr.Metoda ta jest szybsza niż zamknięcia i otwarcia zestawu rekordów na początku każdej transakcji.Poniższy kod demonstruje sposób implementacji tej techniki:
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( );
Innym sposobem zaimplementowania tej techniki jest wpisanie nowej funkcji, RequeryWithBeginTrans, który można zadzwonić do uruchomienia następnej transakcji po zatwierdzeniu lub rollback pierwsza.Aby napisać taką funkcję, wykonaj następujące kroki:
Skopiuj kod (CRecordset::Requery) do nowych funkcji.
Dodaj następujący wiersz natychmiast po wywołaniu SQLFreeStmt:
m_pDatabase->BeginTrans( );
Teraz można wywołać tę funkcję między każdą parą transakcji:
// 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( )
[!UWAGA]
Nie należy używać tej techniki, jeśli trzeba zmienić zmienne składowe zestawu rekordów m_strFilter lub m_strSort między transakcjami.W takim przypadku należy zamknąć zestaw rekordów po każdym CommitTrans lub Rollback operacji.