Webサービスへの呼び出しでは、次のコードを使用して、呼び出し元が有効なセッションを持っていることを確認します。有効なセッションが見つかった場合、セッションの詳細が更新され、変更が保存されます。すべてが十分に単純で、正常に機能します。
// Create the Entity Framework context
using(MyContext ctx = CreateMyContext())
{
// Get the user session for the client session
UserSession session = (from us in context.UserSessions.Include("UserEntity")
where us.SessionId = callerSessionId
select us).FirstOrDefault<UserSession>();
if (session == null)
return false;
else
{
// Update session details
session.Calls++;
session.LastAccessed = DateTime.Now.Ticks;
Console.WriteLine("Call by User:{0}", session.UserEntity.Name);
// Save session changes back to the server
ctx.SaveChanges();
return true;
}
}
同じ呼び出し元、つまり同じセッションが複数の同時呼び出しを行うまで、すべてが正常に機能します(これは完全に有効です)。この場合、デッドロックが発生することがあります。SQL Server Profilerを使用すると、次のことが発生していることがわかります。
発信者Aは選択を実行し、ユーザーセッションの共有ロックを取得します。発信者Bは選択を実行し、同じユーザーセッションで共有ロックを取得します。発信者Bの共有ロックが原因で、発信者Aは更新を実行できません。発信者Aの共有ロックが原因で、発信者Bは更新を実行できません。デッドロック。
これは単純で古典的なデッドロックシナリオのようであり、それを解決するための簡単な方法が必要です。確かに、ほとんどすべての実際のアプリケーションでこれと同じ問題が発生しますが、デッドロックについて言及しているEntityFrameworksの本はありません。