Chr*_*ris 64 c# sql-server ado.net deadlock transactionscope
我有一个在TransactionScope中运行的代码块,在这段代码中,我多次调用DB.选择,更新,创建和删除整个色域.当我执行删除操作时,我使用SqlCommand的扩展方法执行它,如果查询死锁,它将自动重新提交查询,因为此查询可能会遇到死锁.
我相信当遇到死锁并且函数尝试重新提交查询时会发生此问题.这是我收到的错误:
与当前连接关联的事务已完成但尚未处理.必须先处理事务,然后才能使用连接执行SQL语句.
这是执行查询的简单代码(下面的所有代码都在使用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();
Dan*_*Dan 60
不要忘记从TransactionScope中压缩select语句.在SQL Server 2005及更高版本中,即使使用(nolock),仍然会在这些表上创建锁定选择触摸.看看这个,它会告诉你如何设置和使用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 
  } 
} 
Mar*_*cus 42
我发现当事务运行的时间比maxTimeoutfor 更长时,可能会出现此消息System.Transactions.无所谓TransactionOptions.Timeout增加,它不能超过maxTimeout.
默认值maxTimeout设置为10分钟,其值只能在.中修改machine.config
将以下内容(在配置级别中)添加machine.config到修改超时:
<configuration>
    <system.transactions>
        <machineSettings maxTimeout="00:30:00" />
    </system.transactions>
</configuration>
machine.config可以在以下位置找到: %windir%\Microsoft.NET\Framework\[version]\config\machine.config
您可以在此博客文章中阅读更多相关信息:http://thecodesaysitall.blogspot.se/2012/04/long-running-systemtransactions.html
Rol*_*olf 21
我可以重现这个问题.这是一个事务超时.
using (new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 0, 1)))
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        using (var sqlCommand = connection.CreateCommand())
        {
            for (int i = 0; i < 10000; i++)
            {
                sqlCommand.CommandText = "select * from actor";
                using (var sqlDataReader = sqlCommand.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                    }
                }
            }
        }
    }
}
抛出System.InvalidOperationException此消息:
与当前连接关联的事务已完成但尚未处理.必须先处理事务,然后才能使用连接执行SQL语句.
要解决此问题,请使查询运行得更快或增加超时.
Don*_*nie 11
如果内部发生异常TransactionScope,则会回滚.这意味着TransactionScope完成了.您现在必须调用dispose()它并开始新的事务.老实说,我不确定你是否可以重复使用旧的TransactionScope,我从未尝试过,但我不认为.
确认此错误也可能由事务超时引起.只是为了补充Marcus + Rolf所说的内容,如果你没有明确设置超时   TransactionScope,TimeSpan的超时将采用默认值.此默认值是以下值中的较小值:
如果你已经覆盖了本地app.config/ web.config设置,例如
<system.transactions>
<defaultSettings timeout="00:05:00" />
</system.transactions>
但是,这会被machine.config设置为"上限"<machineSettings maxTimeout="00:10:00" />