注释
自联机文档中首次包含此说明以来,尚未更新以下技术说明。 因此,某些过程和主题可能过期或不正确。 有关最新信息,建议在在线文档索引中搜索您感兴趣的主题。
此说明介绍了在使用 MFC ODBC 数据库类和 Microsoft ODBC 桌面驱动程序包版本 3.0 中包含的 Microsoft Access 7.0 ODBC 驱动程序时如何执行事务。
概述
如果数据库应用程序执行事务,则必须注意在应用程序中按正确的顺序调用 CDatabase::BeginTrans
和 CRecordset::Open
排序。 Microsoft Access 7.0 驱动程序使用 Microsoft Jet 数据库引擎,Jet 要求应用程序不在任何具有打开游标的数据库上开始事务。 对于 MFC ODBC 数据库类,打开的游标等同于打开 CRecordset
的对象。
如果在调用 BeginTrans
前打开记录集,则可能看不到任何错误消息。 但是,应用程序在调用 CRecordset::Update
后所做的任何记录集更新都会成为永久的,并且不会通过调用 Rollback
回滚更新。 若要避免此问题,必须先调用 BeginTrans
,然后打开记录集。
MFC 检查驱动程序功能中的游标提交和回滚行为。 类 CDatabase
提供两个成员函数, GetCursorCommitBehavior
用于 GetCursorRollbackBehavior
确定任何事务对打开 CRecordset
对象的影响。 对于 Microsoft Access 7.0 ODBC 驱动程序,这些成员函数会返回 SQL_CB_CLOSE
,因为 Access 驱动程序不支持游标保留。 因此,必须调用 CRecordset::Requery
遵循 CommitTrans
或 Rollback
作。
需要一个接一个地执行多个事务时,不能在第一个事务后调用 Requery
,然后启动下一个事务。 必须在下一次调用 BeginTrans
之前关闭记录集,才能满足 Jet 的要求。 此技术说明描述了处理这种情况的两种方法:
在每个或
Rollback
作后CommitTrans
关闭记录集。使用 ODBC API 函数
SQLFreeStmt
。
在每个 CommitTrans 或回滚作之后关闭记录集
在启动事务之前,请确保记录集对象已关闭。 调用 BeginTrans
后,调用记录集 Open
的成员函数。 调用 CommitTrans
后立即关闭记录集或 Rollback
。 请注意,重复打开和关闭记录集可能会降低应用程序的性能。
使用 SQLFreeStmt
还可以使用 ODBC API 函数 SQLFreeStmt
在结束事务后显式关闭游标。 若要启动另一个事务,请调用 BeginTrans
后跟 CRecordset::Requery
。 调用 SQLFreeStmt
时,必须将记录集的 HSTMT 指定为第一个参数, 并将SQL_CLOSE 指定为第二个参数。 此方法比在每个事务开始时关闭和打开记录集更快。 以下代码演示如何实现此技术:
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();
实现此方法的另一种方法是编写一个新函数, RequeryWithBeginTrans
可以在提交或回滚第一个事务后调用该函数来启动下一个事务。 若要编写此类函数,请执行以下步骤:
将代码
CRecordset::Requery( )
复制到新函数。在调用
SQLFreeStmt
后立即添加以下行:m_pDatabase->BeginTrans( );
现在,可以在每对事务之间调用此函数:
// 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()
注释
如果需要在事务 之间更改 记录集成员变量m_strFilter或 m_strSort, 请不要使用此技术。 在这种情况下,应在每次 CommitTrans
或 Rollback
作后关闭记录集。