我有一个在 TransactionScope 中运行的代码块,在这个代码块中我对数据库进行了多次调用。选择、更新、创建和删除整个范围。当我执行删除时,我使用 SqlCommand 的扩展方法执行它,如果它死锁,它将自动重新提交查询,因为此查询可能会遇到死锁。
我相信当遇到死锁并且函数尝试重新提交查询时会出现问题。这是我收到的错误:
The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements.
这是执行查询的简单代码(以下所有代码都在 TransactionScope 的使用范围内执行):
using (sqlCommand.Connection = new SqlConnection(ConnectionStrings.App))
{
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQueryWithDeadlockHandling();
}
这是重新提交死锁查询的扩展方法:
public static class SqlCommandExtender
{
private const int DEADLOCK_ERROR = 1205;
private const int MAXIMUM_DEADLOCK_RETRIES = 5;
private const int SLEEP_INCREMENT = 100;
public static void ExecuteNonQueryWithDeadlockHandling(this SqlCommand sqlCommand)
{
int count = 0;
SqlException deadlockException = null;
do
{
if (count > 0) Thread.Sleep(count * SLEEP_INCREMENT);
deadlockException = ExecuteNonQuery(sqlCommand);
count++;
}
while (deadlockException != null && count < MAXIMUM_DEADLOCK_RETRIES);
if (deadlockException != null) throw deadlockException;
}
private static SqlException ExecuteNonQuery(SqlCommand sqlCommand)
{
try
{
sqlCommand.ExecuteNonQuery();
}
catch (SqlException exception)
{
if (exception.Number == DEADLOCK_ERROR) return exception;
throw;
}
return null;
}
}
错误发生在线路上:
sqlCommand.ExecuteNonQuery();
最佳答案
不要忘记从您的 TransactionScope 中抑制您的选择语句。在 SQL Server 2005 及更高版本中,即使您使用 with(nolock),仍然会在 select 接触的那些表上创建锁。看看这个,它会告诉你 how to setup and use TransactionScope .
using(TransactionScope ts = new TransactionScope
{
// db calls here are in the transaction
using(TransactionScope tsSuppressed = new TransactionScope (TransactionScopeOption.Suppress))
{
// all db calls here are now not in the transaction
}
}
关于c# - TransactionScope 提前完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2921920/