对我的 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 无法执行其更新。僵局。
这似乎是一个简单而经典的死锁场景,必须有一个简单的方法来解决它。当然,几乎所有现实世界的应用程序都存在同样的问题。但是我在实体框架的书籍中没有提到任何关于死锁的内容。