C# 实体框架线程安全

C# 实体框架线程安全,c#,concurrency,entity-framework-4,thread-safety,datacontext,C#,Concurrency,Entity Framework 4,Thread Safety,Datacontext,实体框架生成的上下文对象不是线程安全的 如果我使用两个单独的实体上下文,每个线程一个(并在每个线程上调用SaveChanges()),这是线程安全的吗 // this method is called from several threads concurrently public void IncrementProperty() { var context = new MyEntities(); context.SomeObject.SomeIntProperty++; c

实体框架生成的上下文对象不是线程安全的

如果我使用两个单独的实体上下文,每个线程一个(并在每个线程上调用
SaveChanges()
),这是线程安全的吗

// this method is called from several threads concurrently
public void IncrementProperty()
{
   var context = new MyEntities();

   context.SomeObject.SomeIntProperty++;
   context.SaveChanges();
}
我相信实体框架上下文实现了某种“计数器”变量,它跟踪上下文中的当前值是否为新值

  • 对于上面的代码(从单独的线程调用),我还需要锁定增量/保存更改吗
  • 如果是这样,在这个简单的场景中,实现这一点的首选方法是什么

  • 我相信“SomeObject.SomeIntProperty”是静态的。这与实体是线程安全的无关。如果在多线程环境中写入静态变量,则应始终使用双重检查锁对其进行包装,以确保线程安全。

    在单个实体框架上下文上操作的多个线程不是线程安全的

    每个线程的上下文的单独实例是线程安全的。只要每个执行线程都有自己的EF上下文实例,就可以了

    在您的示例中,您可以同时从任意数量的线程调用该代码,并且每个线程都可以愉快地使用自己的上下文

    但是,我建议为此实现一个“使用”块,如下所示:

    // this method is called from several threads concurrently
    public void IncrementProperty()
    {
       using (var context = new MyEntities())
       {
          context.SomeObject.SomeIntProperty++;
          context.SaveChanges();
       }
    }
    

    您可以使用工厂方法将DbContext作为工厂而不是实例perse注入,请看以下内容:

    这样更安全,而且避免将实例创建硬编码到存储库中


    Ninject有一个扩展,可以非常简单地实现这一点,只需调用方法
    kernel.AddDbContextFactory()
    您还需要通过接收
    Func

    “Entity Framework生成的上下文对象不是线程安全的。”-为什么这么说?我指的是MSDN:其中说“ObjectContext类不是线程安全的。”是的,这就是我认为您的意思-上下文,而不是实体。这就是为什么你不应该在OC中使用单例。那么,在执行SubmitChanges()或在什么时候读取SomeIntProperty的实际值呢?我的意思是,如果第一个线程将值增加到3,那么第二个线程是否仍有可能将值2缓存在某个地方,或者它是否会当场检索该值?我忽略了示例中的几个重要方面。首先,您没有检索和实例“SomeObject”的代码。因此,如图所示,代码将不起作用。上下文之间不共享缓存、缓冲区或锁。因此,每个线程及其上下文实例可以被认为是在两台不同的机器上运行的进程。因此,您必须相应地处理数据库并发问题。您需要实现乐观并发或数据库事务来处理数据库并发问题。