Я столкнулся с неожиданным поведением при использовании ADO с C++ и Microsoft SQL Server 2008 (экспресс). По сути, у меня был код, который делал это:
//pseudocode pseudocode pseudocode
adoConnection->Execute("BEGIN TRANSACTION;");
Insert( adoRecordsetPtr );
SelectAll( adoRecordsetPtr );
adoConnection->Execute("COMMIT TRANSACTION;");
Но когда он попытался выполнить SelectAll, ADO выдало исключение со следующей информацией:
Ошибка: Ошибка ADO -2147217871: 071A14D0
Из источника: Microsoft OLE DB Provider для 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 );