在将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
源自:用于SQL Server的Microsoft OLE DB提供程序
说明:超时已过期
经过一番调查,我发现如果我使用ado_connection-> BeginTrans(),就像一个理智的人一样,一切都按预期工作。虽然这篇文章主要是为了让其他可能遇到它的人可以使用变通方法,但我也有一个问题:
为什么这样可以解决问题?
以下是有关Insert和SelectAll正在发生的事情的详细信息。请注意,SelectAll正在使用ADO命令对象(因为在实际代码中它没有执行select all)。如果我使用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 );
答案 0 :(得分:1)
简短的回答是BEGIN TRANSACTION
和cn.BeginTrans()
的行为方式并不一样。这个MSDN article会告诉您有关此问题的更多信息:
ADO如何处理交易
默认情况下,ADO在AutoCommit模式下运行,除非您通过执行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
......也许不是你所期待的。