Проверьте, находится ли соединение в транзакции - PullRequest
2 голосов
/ 18 мая 2010

Я получаю SqlConnection does not support parallel transactions. исключение и в этом ответе упоминает его, когда соединение пытается открыть две транзакции. Это именно то, что я делаю. Я думал, что вложенные транзакции были в порядке (я использовал sqlite для прототипа).

Как проверить, установлено ли соединение в транзакции? Я использую файл базы данных Microsoft SQL Server.

Ответы [ 4 ]

6 голосов
/ 18 мая 2010

После некоторого поиска я нашел этот вопрос переполнения стека . Оказывается, вы не можете вкладывать транзакции в ADO.NET. При попытке вы, вероятно, в конечном итоге запускаете две несвязанные транзакции, что приводит к ошибке параллельных транзакций.

Чтобы увидеть, находится ли соединение в данный момент в транзакции, вы можете:

var com = yourConnection.CreateCommand();
com.CommandText = "select @@TRANCOUNT";
var trancount = com.ExecuteScalar();

Возвращает количество вложенных транзакций.

Обратите внимание, что вы можете вкладывать транзакции вручную, без использования объекта SqlTransaction. Например:

var com = yourConnection.CreateCommand();
com.CommandText = "BEGIN TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "BEGIN TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "INSERT INTO TestTable (name) values ('Joe');";
com.ExecuteNonQuery();
com.CommandText = "COMMIT TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "ROlLBACK TRANSACTION";
com.ExecuteNonQuery();

com.CommandText = "SELECT COUNT(*) FROM TestTable";
Console.WriteLine("Found {0} rows.", com.ExecuteScalar());

Это печатает 0, потому что вложенная транзакция была прервана полностью.

2 голосов
/ 18 мая 2010

Вы делаете это из нескольких потоков? Если это так, то запрос не поможет, потому что между временем запроса и началом новой транзакции какой-то другой поток мог начать свою собственную транзакцию. Вы захотите использовать пул соединений, чтобы избежать такого рода условий гонки.

0 голосов
/ 27 октября 2016

Вы можете проверить, открыта ли уже транзакция, проверив, является ли cmd.Transaction null.

Затем оберните ваш код соответствующим образом, так что если транзакция уже открыта, то вызывающая функция владеет этой транзакцией и будет фиксировать / откатывать ее соответствующим образом.

//begin transaction unless one was already started
bool newTransaction = cmd.Transaction == null;
if (newTransaction) cmd.Transaction = cmd.Connection.BeginTransaction();

try {
    // do Stuff Here
    cmd.ExecuteNonQuery();
    cmd.ExecuteNonQuery();

    // commit if it's our to commit
    if (newTransaction) cmd.Transaction.Commit();

} catch (SqlException ex) {
    if (newTransaction && cmd.Transaction != null) cmd.Transaction.Rollback();
    throw;
}

Затем родительская функция может передать команду и, при желании, выбрать начало своего собственного транзакционного блока, или, если нет, он будет создан и передан вызываемой функцией.

0 голосов
/ 18 мая 2010

Я думаю, что когда ваш код не знает его, это сделает только Try / Catch. На каком языке?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...