Я хочу обновить некоторые строки в базе данных MS SQL с C++. Проблема в том, что я не могу создать транзакцию. Каждый раз, когда я пытаюсь выполнить Ado::Connection::BeginTrans
, я получаю сообщение об ошибке:
A request to establish a connection with the transaction manager was denied.
Я установил новую копию SQL Server 2017 Express Edition на свой локальный компьютер (Win 10 Pro) и создал новую БД под названием test
.
Строка подключения:
Provider=SQLNCLI11;Server=SNAIL\SQLEXPRESS;Database=test;Trusted_Connection=yes;
Что мне делать, чтобы избавиться от этой ошибки?
Обновлено:
Часть исходного кода:
#import <msado15.dll> rename_namespace("ADO2"), raw_interfaces_only, raw_native_types, named_guids, no_smart_pointers
const auto connection_string = L"Provider=sqloledb;Data Source=SNAIL\\SQLEXPRESS;Initial Catalog=test;Integrated Security=SSPI";
// create connection
Ref<ADO2::_Connection> m_DbConnection;
m_DbConnection->put_Mode(ADO2::adModeReadWrite);
m_DbConnection->put_ConnectionTimeout(5);
m_DbConnection->Open(connection_string, nullptr, nullptr, ADO2::adConnectUnspecified)
class InAdoTransaction {
private:
Ref<ADO2::_Connection> m_DbConnection;
bool m_Commited;
public:
InAdoTransaction(ADO2::_Connection *Connection) {
m_DbConnection = Connection;
m_Commited = false;
long transaction_level;
HRESULT er = m_DbConnection->BeginTrans(&transaction_level);
ASSERT(er == S_OK);
}
~InAdoTransaction() {
if (!m_Commited) {
Rollback();
}
}
void Rollback() {
m_DbConnection->RollbackTrans();
}
void Commit() {
m_DbConnection->CommitTrans();
m_Commited = true;
}
};
// usage
HRESULT FUNC StoreMetadata()
{
HRESULT er = S_OK;
Ref<ADO2::_Recordset> rst;
InAdoTransaction transaction(m_DbConnection);
if (FAILED(m_DbConnection->Execute(QUERY_TRUNCATE_METADATA_TABLE, nullptr, 0, OUT(rst)))) {
return E_CANNOT_STORE_METADATA;
}
...
transaction.Commit();
}
Некоторый код может помочь. Документы предлагают пример, который действительно ужасен, но может дать вам ключ к пониманию того, что вы делаете неправильно. (Однако определенно не используйте поставщика sqloledb
, который он вам там показывает; sqlncli11
подойдет, или более новый msoledbsql
, который требует отдельной установки.)
Вы перезагружались после установки SQL Server Express? Работает ли служба координатора распределенных транзакций?
Вы, вероятно, не должен тоже используете SQLNCLI11
. Это устарело и все новые разработки были направлены на драйверы ODBC и OLEDB. ADO в любом случае работает поверх OLEDB, поэтому использование клиента OLEDB с "Provider='sqloledb'
вообще не изменит код.
Эта конкретная ошибка означает, что каким-то образом код пытался запустить транзакцию распределенный. Для этого требуется DTC и, вероятно, нет то, что вам нужно. Простая команда BEGIN TRAN
не требует DTC. Connection.BeginTrans()
также не должен нуждаться в DTC.
С другой стороны, использование, например, связанного сервера в запросе требует распределенной транзакции и попытается использовать MS DTC.
Я также пробовал 'sqloledb', но поведение такое же. + Я добавил фрагмент кода к вопросу.
Я наконец нашел решение. Вся проблема была в наборе записей, который я создал для таблиц INFORMATION_SCHEMA.TABLES
и INFORMATION_SCHEMA.VIEWS
. Тип блокировки этого набора записей был установлен на LockType::adLockReadOnly
, что и вызвало проблему. Я изменил его на LockType::adLockOptimistic
и теперь все работает как часы.
Но очень жаль, что провайдер возвращает такое вводящее в заблуждение сообщение об ошибке.
Разместите свой код. Транзакции работают с ADO. В конце концов, это технология, которой более 25 лет.