トランザクション スコープにラップされたコード ブロックがあります。データベースとの通信に LINQ を使用しています。デッドロック例外をキャプチャしたら、トランザクションを再送信するにはどうすればよいですか?
3415 次
2 に答える
4
基本的には、デッドロック例外をキャッチしてコードを再試行するだけです。次のようにします。
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() を呼び出すことに注意してください。私たちのソリューションには、あなたが求めているものよりも少し多くのことがありますが、これで一般的な方向性が得られるはずです.
于 2012-08-31T23:42:44.530 に答える
1
何よりもまず、デッドロックが発生した理由を考えてください。LINQ コンテキストで読み取って変更した値が別のトランザクションによって変更されたためですか? 唯一の合理的なアクションは、値を再度読み取り、変更が新しい値で意味があるかどうかを判断することです。これは ASP.NET であるため、ユーザーに新しい値を表示することを意味するため、変更が発生したことを通知してユーザーにページを再度戻す必要があり、データを再度編集する必要があります。
デッドロック時の自動再送信は可能ですが、ほとんどの場合、お勧めできません。再試行によって値が読み取られた後に発生した変更が上書きされるため、ドメイン ルールが破られるため、データベースの状態が悪化する可能性があります。
于 2012-09-01T06:52:09.683 に答える