TN068:使用 Microsoft Access 7 ODBC 驱动程序执行事务

注释

自联机文档中首次包含此说明以来,尚未更新以下技术说明。 因此,某些过程和主题可能过期或不正确。 有关最新信息,建议在在线文档索引中搜索您感兴趣的主题。

此说明介绍了在使用 MFC ODBC 数据库类和 Microsoft ODBC 桌面驱动程序包版本 3.0 中包含的 Microsoft Access 7.0 ODBC 驱动程序时如何执行事务。

概述

如果数据库应用程序执行事务,则必须注意在应用程序中按正确的顺序调用 CDatabase::BeginTransCRecordset::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 遵循 CommitTransRollback 作。

需要一个接一个地执行多个事务时,不能在第一个事务后调用 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可以在提交或回滚第一个事务后调用该函数来启动下一个事务。 若要编写此类函数,请执行以下步骤:

  1. 将代码 CRecordset::Requery( ) 复制到新函数。

  2. 在调用 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, 请不要使用此技术。 在这种情况下,应在每次 CommitTransRollback 作后关闭记录集。

另请参阅

按编号列出的技术说明
按类别列出的技术说明