gpt4 book ai didi

c++ - 为什么 ADO BeginTrans() 做的事情与 "BEGIN TRANSACTION"不同?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:36:10 24 4
gpt4 key购买 nike

在将 ADO 与 C++ 和 Microsoft SQL Server 2008 (express) 结合使用时,我遇到了一些令人惊讶的行为。本质上,我有执行此操作的代码:

//pseudocode pseudocode pseudocode   
adoConnection->Execute("BEGIN TRANSACTION;");
Insert( adoRecordsetPtr );
SelectAll( adoRecordsetPtr );
adoConnection->Execute("COMMIT TRANSACTION;");

但是当它尝试执行 SelectAll 时,ADO 抛出了一个异常并显示以下信息:

错误:ADO错误-2147217871:071A14D0
来源:Microsoft OLE DB Provider for SQL Server
说明:超时超时

经过一番调查,我发现如果我使用 ado_connection->BeginTrans(),就像正常人一样,一切都会按预期进行。虽然这篇文章主要是为了让其他可能遇到它的人可以通过谷歌搜索解决方法,但我也有一个问题:

为什么这解决了问题?

这里有一些关于我的 Insert 和 SelectAll 发生的事情的更多细节。请注意,SelectAll 使用的是 ADO 命令对象(因为在实际代码中它并未执行全选)。如果我使用 Connection.Execute() 而不是 Command.Execute(),则不会发生超时。

//Insert
ADODB::_RecordsetPtr prs = NULL;
HRESULT hr = prs.CreateInstance(__uuidof(ADODB::Recordset));
prs->Open(
table
_variant_t((IDispatch *) acpAdoConnection),
ADODB::adOpenUnspecified,
ADODB::adLockOptimistic,
ADODB::adCmdTable);
prs->AddNew();
//put some stuff into fields using prs->Fields->Item[]
prs->Update();
prs->Close();

//SelectAll
ADODB::_CommandPtr cmd;
cmd.CreateInstance( __uuidof( ADODB::Command ) );
cmd->ActiveConnection = acpAdoConnection;
ADODB::_RecordsetPtr prs2 = NULL;
HRESULT hr2 = prs2.CreateInstance(__uuidof(ADODB::Recordset));
prs2->Open(
table,
_variant_t((IDispatch *) acpAdoConnection),
ADODB::adOpenUnspecified,
ADODB::adLockOptimistic,
ADODB::adCmdTable);
std::string sql = "SELECT * FROM [" + table + "] ;";
cmd->CommandText = sql.c_str();
_variant_t vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR);
_variant_t vtEmpty2(DISP_E_PARAMNOTFOUND, VT_ERROR);
//timeout:
ADODB::_RecordsetPtr records =
cmd->Execute( &vtEmpty, &vtEmpty2, ADODB::adCmdText );

最佳答案

简短的回答是 BEGIN TRANSACTIONcn.BeginTrans() 的行为方式并不总是相同。这MSDN article告诉你更多关于这个问题的信息:


ADO 如何处理事务

默认情况下,ADO 在自动提交模式下运行,除非您通过执行 Connection.BeginTrans 启动隐式事务。

Implicit_transactions 在服务器上为每个语句开始一个事务,并且在手动发出之前不会发生提交。

所以,

set implicit_transactions on
go
insert
insert
insert

在内部变成了

BEGIN TRAN
insert
insert
insert
...

除非用户发出正确的声明,否则上述事务不会被回滚或提交。

如果没有隐式事务(默认情况下是 ADO(自动提交模式)的行为),将(概念上)发生以下情况:

BEGIN TRAN
insert
COMMIT TRAN
BEGIN TRAN
insert
COMMIT TRAN

如您所见,对于您的情况

BEGIN TRAN
insert
COMMIT TRAN
BEGIN TRAN
select
COMMIT TRAN

不同于:

BEGIN TRAN
insert
select
COMMIT TRAN

... 也可能不是您所期望的。

关于c++ - 为什么 ADO BeginTrans() 做的事情与 "BEGIN TRANSACTION"不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3998209/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com