2

如果两个请求在 ASP.NET MVC 应用程序中非常接近,我会使用以下代码出现竞争条件:

var workload = org.Workloads.SingleOrDefault(p => ...conditions...);
if (workload == null) {
    workload = org.CreateWorkload(id);
}

workload并且org是 EntityFramework 对象。调用向CreateWorkload数据库中的工作负载表添加一行。(我们确实应该在表上使用 UNIQUE 约束来强制执行此操作,但我现在不能因为表中有一些脏数据。SingleOrDefault )当遇到多行时,对包含此代码的 Action 方法的后续调用会引发异常满足条件。

所以要解决这个问题,我想要lock这些代码行。我不希望它按请求完成,使用静态锁定对象,因为这会减慢每个用户的网站速度。我想做的是Session.SyncRoot用于锁定。IE

Workload workload;
lock (Session.SyncRoot) 
{
    workload = org.Workloads.SingleOrDefault(p => ...conditions...);
    if (workload == null) {
        workload = org.CreateWorkload(id);
    }
}

但是,我不是 ASP.NET 专家,并且在文档和 ReSharper 中出现了一些警告标志,即它可以抛出 NotImplementedExceptions 或为 null。但是,测试表明这很好用。

那么,ASP.NET 专家,为此使用 Session.SyncRoot 有什么风险?作为替代方案,如果 Session.SyncRoot “真的很危险”,我可以在 Session 启动时在 Session 集合中分配一个锁对象来做同样的事情吗?

4

1 回答 1

2

仅当您使用实现HttpSessionStateBase但不覆盖该SyncRoot属性的自定义会话类来执行除抛出 NotImplementedException 之外的其他操作时,才会存在危险。类HttpSessionStateWrapperHttpSessionState类 DO 实现并覆盖该SyncRoot方法。因此,只要您通过HttpSessionStateWrapperorHttpSessionState类而不是自定义类访问 Session,就可以正常工作。

于 2013-06-07T06:13:41.090 回答