SQLTransaction завершила ошибку
Я получил следующую ошибку один раз в своем приложении.
Это SQLTransaction завершено; он больше не используется
След стека приведен ниже: он говорит о Zombie Check
и Rollback
.
Какая ошибка в коде?
Примечание. Эта ошибка появилась только один раз.
UPDATE
От MSDN - метод SqlTransaction.Rollback
Откат генерирует исключение InvalidOperationException, если соединение завершено или транзакция уже откатна на сервере.
От Проверка Zombie на транзакции - Ошибка
Одна из самых частых причин, по которым я обнаружил эту ошибку в различных приложениях, - это совместное использование SqlConnection в нашем приложении.
CODE
public int SaveUserLogOnInfo(int empID)
{
int? sessionID = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
sessionID = GetSessionIDForAssociate(connection, empID, transaction);
//Other Code
//Commit
transaction.Commit();
}
catch
{
//Rollback
if (transaction != null)
{
transaction.Rollback();
transaction.Dispose();
transaction = null;
}
//Throw exception
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
return Convert.ToInt32(sessionID,CultureInfo.InvariantCulture);
}
Трассировка стека
![enter image description here]()
ССЫЛКА:
Ответы
Ответ 1
Вы должны оставить часть работы компилятору, чтобы обернуть это в try
/catch
/finally
для вас.
Кроме того, вы должны ожидать, что Rollback
может иногда генерировать исключение, если проблема возникает на этапе Commit
или если соединение с сервером прерывается. По этой причине вы должны обернуть его в try
/catch
.
try
{
transaction.Rollback();
}
catch (Exception ex2)
{
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
Console.WriteLine(" Message: {0}", ex2.Message);
}
Это скопировано именно с страницы документации MSDN для метода отката.
Я вижу, что вы обеспокоены тем, что у вас есть транзакция с зомби. Если вы вставили, это не похоже на то, что у вас есть проблема. Вы совершили транзакцию, и вам больше нечего с ней делать. Удалите ссылки на него, если вы их удерживаете, и забудьте об этом.
От Метод MSDN - SqlTransaction.Rollback
Откат генерирует исключение InvalidOperationException, если соединение завершено или транзакция уже откатна на сервере.
Повторите новое исключение, чтобы сообщить пользователю, что данные могут быть не сохранены, и попросите ее обновить и просмотреть
Ответ 2
Примечание. Эта ошибка появилась только один раз.
тогда очень сложно сказать много; это может быть просто, что // Other Code
и т.д. просто занял много времени, и вся вещь была убита. Возможно, ваша связь умерла, или администратор умышленно убил ее, потому что вы блокировали.
Какая ошибка в коде?
чрезмерное его усложнение; это может быть намного проще:
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using(var transaction = connection.BeginTransaction())
{
try
{
sessionID = GetSessionIDForAssociate(connection, empID, transaction);
//Other Code
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
гораздо меньше кода, чтобы ошибиться.
Ответ 3
Я однажды испытал эту ошибку, и я застрял и не мог понять, что происходит. На самом деле я удалял запись, а в Хранимой процедуре я не удалял ее дочерний элемент, и особенно оператор delete в Stored Procedure
находилась внутри границы Transaction
. Я удалил этот код транзакции из хранимой процедуры и избавился от получения этой ошибки "This SqlTransaction has completed; it is no longer usable."
Ответ 4
Я использую приведенный ниже код, могу воспроизвести эту ошибку, я использую 1000 задач для выполнения Sql, после того, как примерно 300 задач успешно завершены, начинается множество исключений о timeout error
на ExecuteNonQuery()
,
то следующая ошибка This SqlTransaction has completed
появится на transaction.RollBack();
, а в стеке вызовов также будет ZombieCheck()
.
(Если одна программа с заданием 1000 задач недостаточно, вы можете одновременно выполнить несколько скомпилированных файлов exe или даже использовать несколько компьютеров для одной базы данных.)
Итак, я думаю, одна из причин, по которой эта ошибка может быть что-то неправильное в Connection, затем вызывает ошибку транзакции.
Task[] tasks = new Task[1000];
for (int i = 0; i < 1000; i++)
{
int j = i;
tasks[i] = new Task(() =>
ExecuteSqlTransaction("YourConnectionString", j)
);
}
foreach (Task task in tasks)
{
task.Start();
}
/////////////
public void ExecuteSqlTransaction(string connectionString, int exeSqlCou)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;
// Start a local transaction.
transaction = connection.BeginTransaction();
// Must assign both transaction object and connection
// to Command object for a pending local transaction
command.Connection = connection;
command.Transaction = transaction;
try
{
command.CommandText =
"select * from Employee";
command.ExecuteNonQuery();
// Attempt to commit the transaction.
transaction.Commit();
Console.WriteLine("Execute Sql to database."
+ exeSqlCou);
}
catch (Exception ex)
{
Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
Console.WriteLine(" Message: {0}", ex.Message);
// Attempt to roll back the transaction.
try
{
transaction.Rollback();
}
catch (Exception ex2)
{
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
Console.WriteLine(" Message: {0}", ex2.Message);
}
}
}
}
Кроме того, я обнаружил, что если я совершу дважды в секвенции, вы также вызовете это исключение.
transaction.Commit();
transaction.Commit();
Или если Connection Closed before commit также вызывает эту ошибку.
connection.Close();
transaction.Commit();
Update:
Мне странно, что я создаю новую новую таблицу и вставляю ей 500 тысяч данных,
затем используйте 100000 задач с select * from newtable
sql, одновременно запустив 5 программ, на этот раз возникла ошибка таймаута, но когда transaction.Rollback()
он не вызывал SQLTransaction has completed error
.
но если произошла ошибка тайм-аута, перейдите в блок catch и в блоке catch снова выполните transaction.Commit()
, произойдет SQLTransaction has completed error
.
Ответ 5
Это сообщение просто потому, что вы написали код, который генерирует исключение после успешной транзакции . Пожалуйста, попробуйте проверить код, который вы написали после метода Commit или , который вы можете обрабатывайте его с помощью Try..Catch и, наконец, Blocks:).
Ответ 6
я столкнулся с той же проблемой, а затем решил ее. Попробуйте найти нежелательные соединения с потоком кода и используйте одно и то же соединение для всех кодов доступа db. :-)