注释
自联机文档中首次包含此说明以来,尚未更新以下技术说明。 因此,某些过程和主题可能过期或不正确。 有关最新信息,建议在在线文档索引中搜索您感兴趣的主题。
此说明介绍了在使用 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 的要求。 此技术说明描述了处理这种情况的两种方法:
在每个或
CommitTrans作后Rollback关闭记录集。使用 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 作后关闭记录集。