会话分隔 SQL Server Native Client OLE DB 提供程序本地事务的事务范围。 当 SQL Server Native Client OLE DB 访问接口向连接的 SQL Server 实例提交请求时,该请求构成了 SQL Server Native Client OLE DB 访问接口的工作单元。 本地事务始终在单个 SQL Server Native Client OLE DB 访问接口会话上包装一个或多个工作单元。
使用默认的 SQL Server Native Client OLE DB 提供程序自动提交模式,单个工作单元被视为本地事务的范围。 只有一个单元参与本地事务。 创建会话时,SQL Server Native Client OLE DB 访问接口将开始会话的事务。 成功完成工作单元后,将提交工作。 失败时,将回滚任何工作,并将错误报告给使用者。 在任一情况下,SQL Server Native Client OLE DB 提供程序都会为会话启动新的本地事务,以便所有工作都在事务中执行。
SQL Server Native Client OLE DB 访问接口可以使用 ITransactionLocal 接口更准确地控制本地事务范围。 当使用者会话启动事务时,事务起始点和最终 提交 或 中止 方法调用之间的所有会话工作单元都被视为原子单元。 当使用者定向到该事务时,SQL Server Native Client OLE DB 提供程序会隐式启动事务。 如果使用者不请求保留,会话将还原为父事务级行为,最常见的是自动提交模式。
SQL Server Native Client OLE DB 提供程序支持 ITransactionLocal::StartTransaction 参数,如下所示。
| 参数 | DESCRIPTION |
|---|---|
| isoLevel[in] | 要用于此事务的隔离级别。 在本地事务中,SQL Server Native Client OLE DB 访问接口支持以下各项: - ISOLATIONLEVEL_UNSPECIFIED - ISOLATIONLEVEL_CHAOS - ISOLATIONLEVEL_READUNCOMMITTED - ISOLATIONLEVEL_READCOMMITTED - ISOLATIONLEVEL_REPEATABLEREAD - ISOLATIONLEVEL_CURSORSTABILITY - ISOLATIONLEVEL_REPEATABLEREAD - ISOLATIONLEVEL_SERIALIZABLE - ISOLATIONLEVEL_ISOLATED - ISOLATIONLEVEL_SNAPSHOT 注意: 从 SQL Server 2005 开始,无论是否为数据库启用版本控制,ISOLATIONLEVEL_SNAPSHOT对 isoLevel 参数有效。 但是,如果用户尝试执行语句和版本控制未启用,并且/或数据库不是只读的,则会发生错误。 此外,如果在连接到低于 SQL Server 2005 的 SQL Server 版本时将ISOLATIONLEVEL_SNAPSHOT指定为 isoLevel ,则会发生错误XACT_E_ISOLATIONLEVEL。 |
| isoFlags[in] | SQL Server Native Client OLE DB 访问接口返回除零以外的任何值的错误。 |
| pOtherOptions[in] | 如果不是 NULL,则 SQL Server Native Client OLE DB 提供程序从接口请求 options 对象。 如果 options 对象的 ulTimeout 成员不为零,则 SQL Server Native Client OLE DB 访问接口返回XACT_E_NOTIMEOUT。 SQL Server Native Client OLE DB 访问接口忽略 szDescription 成员的值。 |
| pulTransactionLevel[out] | 如果不是 NULL,则 SQL Server Native Client OLE DB 访问接口返回事务的嵌套级别。 |
对于本地事务,SQL Server Native Client OLE DB 提供程序实现 ITransaction::Abort 参数,如下所示。
| 参数 | DESCRIPTION |
|---|---|
| pboidReason[in] | 如果已设置,则忽略。 可以安全地为 NULL。 |
| fRetaining[in] | 如果为 TRUE,则会隐式启动会话的新事务。 事务必须由使用者提交或终止。 如果为 FALSE,SQL Server Native Client OLE DB 访问接口将还原为会话的自动提交模式。 |
| fAsync[in] | SQL Server Native Client OLE DB 访问接口不支持异步中止。 如果值不为 FALSE,SQL Server Native Client OLE DB 访问接口将返回XACT_E_NOTSUPPORTED。 |
对于本地事务,SQL Server Native Client OLE DB 提供程序实现 ITransaction::Commit 参数,如下所示。
| 参数 | DESCRIPTION |
|---|---|
| fRetaining[in] | 如果为 TRUE,则会隐式启动会话的新事务。 事务必须由使用者提交或终止。 如果为 FALSE,SQL Server Native Client OLE DB 访问接口将还原为会话的自动提交模式。 |
| grfTC[in] | SQL Server Native Client OLE DB 访问接口不支持异步返回和第一阶段返回。 SQL Server Native Client OLE DB 访问接口返回除XACTTC_SYNC以外的任何值XACT_E_NOTSUPPORTED。 |
| grfRM[in] | 必须为 0。 |
会话上的 SQL Server Native Client OLE DB 访问接口行集将保留在本地提交或中止作上,具体取决于行集属性的值DBPROP_ABORTPRESERVE和DBPROP_COMMITPRESERVE。 默认情况下,这些属性都是VARIANT_FALSE,会话上的所有 SQL Server Native Client OLE DB 提供程序行集在中止或提交作后都会丢失。
SQL Server Native Client OLE DB 访问接口不实现 ITransactionObject 接口。 使用者尝试检索接口上的引用将返回E_NOINTERFACE。
此示例使用 ITransactionLocal。
// Interfaces used in the example.
IDBCreateSession* pIDBCreateSession = NULL;
ITransaction* pITransaction = NULL;
IDBCreateCommand* pIDBCreateCommand = NULL;
IRowset* pIRowset = NULL;
HRESULT hr;
// Get the command creation and local transaction interfaces for the
// session.
if (FAILED(hr = pIDBCreateSession->CreateSession(NULL,
IID_IDBCreateCommand, (IUnknown**) &pIDBCreateCommand)))
{
// Process error from session creation. Release any references and
// return.
}
if (FAILED(hr = pIDBCreateCommand->QueryInterface(IID_ITransactionLocal,
(void**) &pITransaction)))
{
// Process error. Release any references and return.
}
// Start the local transaction.
if (FAILED(hr = ((ITransactionLocal*) pITransaction)->StartTransaction(
ISOLATIONLEVEL_REPEATABLEREAD, 0, NULL, NULL)))
{
// Process error from StartTransaction. Release any references and
// return.
}
// Get data into a rowset, then update the data. Functions are not
// illustrated in this example.
if (FAILED(hr = ExecuteCommand(pIDBCreateCommand, &pIRowset)))
{
// Release any references and return.
}
// If rowset data update fails, then terminate the transaction, else
// commit. The example doesn't retain the rowset.
if (FAILED(hr = UpdateDataInRowset(pIRowset, bDelayedUpdate)))
{
// Get error from update, then terminate.
pITransaction->Abort(NULL, FALSE, FALSE);
}
else
{
if (FAILED(hr = pITransaction->Commit(FALSE, XACTTC_SYNC, 0)))
{
// Get error from failed commit.
}
}
if (FAILED(hr))
{
// Update of data or commit failed. Release any references and
// return.
}
// Release any references and continue.