C# 死锁后重新提交事务
我有一个代码块包装在事务作用域中。我正在使用LINQ与数据库通信。捕获死锁异常后,如何重新提交事务?基本上,您只需捕获死锁异常并重试代码。我们这样做:C# 死锁后重新提交事务,c#,asp.net,.net,sql-server,linq-to-sql,C#,Asp.net,.net,Sql Server,Linq To Sql,我有一个代码块包装在事务作用域中。我正在使用LINQ与数据库通信。捕获死锁异常后,如何重新提交事务?基本上,您只需捕获死锁异常并重试代码。我们这样做: private static void ExecuteWithDeadlockRetry(int maxAttempts, bool useTransaction, Action action) { int tryCount = 0; string errorMessage; // If use transaction
private static void ExecuteWithDeadlockRetry(int maxAttempts, bool useTransaction, Action action)
{
int tryCount = 0;
string errorMessage;
// If use transaction is true and there is an existing ambient transaction (means we're in a transaction already)
// then it will not do any good to attempt any retries, so set max retry limit to 1.
if (useTransaction && Transaction.Current != null) { maxAttempts = 1; }
do
{
try
{
// increment the try count...
tryCount++;
if (useTransaction)
{
// execute the action inside a transaction...
using (TransactionScope transactionScope = new TransactionScope())
{
action();
transactionScope.Complete();
}
}
else
action();
// If here, execution was successful, so we can return...
return;
}
catch (SqlException sqlException)
{
if (sqlException.Number == (int)SqlExceptionNumber.Deadlock && tryCount < maxAttempts)
{
// Log error here
}
else
{
throw;
}
}
} while (tryCount <= maxAttempts);
}
SqlDeadlockHelper.Execute(() =>
{
// Code to execute here
}
请注意,Execute()方法最终调用ExecuteWithDeadlockRetry()。我们的解决方案比您要求的要多一些,但这应该给您一些大致的指导。首先思考一下为什么会出现僵局?是因为您在LINQ上下文中读取并修改的值被另一个事务更改了吗?唯一合理的做法是再次读取这些值,并确定您的更改对新值是否有意义。由于这是ASP.NET,这意味着向用户显示新的值,因此您必须再次将页面返回给用户,并通知用户发生了更改,并且必须再次编辑数据
死锁时自动重新提交是可能的,但几乎总是一个坏主意。这很可能会导致数据库中出现错误状态,因为您的域规则被破坏,因为您的重试会覆盖读取该值后发生的更改。如果您是这样,您几乎是在要求发生死锁!使用explicit将隔离级别更改为远离…为什么要使用transactionscope。您是否有多个提交更改?9/10倍,这是不必要的。