我有一段代码,在TransactionScope内运行,在这段代码中,我对数据库进行了多次调用。 包括选择、更新、创建和删除等操作。当我执行删除操作时,我使用SqlCommand的扩展方法执行它,如果此查询可能会出现死锁,它将自动重新提交查询。
我认为问题出在出现死锁时,函数尝试重新提交查询。 这就是我收到的错误消息:
与当前连接关联的事务已完成但未被处理。 必须处理该事务后才能使用连接来执行SQL语句。
这是执行查询的简单代码(以下所有代码都在TransactionScope的using内部执行):
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();
Serializable
TS隔离级别的结果。通常最好的解决方法是将TS创建包装在一个类工厂中,该类工厂将序列化设置为更合理的选项,例如Read Comitted。详见:https://dev59.com/sGgu5IYBdhLWcg3we3Ct - StuartLC