实体框架线程安全

时间:2010-12-15 22:31:21

标签: c# concurrency entity-framework-4 thread-safety datacontext

Entity Framework生成的上下文对象不是线程安全的。

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

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

   context.SomeObject.SomeIntProperty++;
   context.SaveChanges();
}

我相信实体框架上下文实现了某种“计数器”变量,它跟踪上下文中的当前值是否是新鲜的。

  1. 使用上面的代码 - 从单独的线程调用 - 我是否还需要锁定增量/保存更改?
  2. 如果是这样,在这个简单的场景中完成此任务的首选方法是什么?

3 个答案:

答案 0 :(得分:39)

更多的是,在单个Entity Framework上下文上运行的一个线程不是线程安全的。

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

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

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

您可以使用工厂方法将DbContext注入工厂而不是实例perse,请看一下:https://github.com/vany0114/EF.DbContextFactory

它更安全,您可以避免将实例创建硬编码到您的存储库中。

http://elvanydev.com/EF-DbContextFactory/

Ninject有一个扩展,以非常简单的方式执行此操作,只需调用方法kernel.AddDbContextFactory<YourContext>();,您还需要通过接收Func<YourContext>来更改存储库