【问题标题】:Entity Framework Thread Safety实体框架线程安全
【发布时间】:2011-05-26 05:35:41
【问题描述】:

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. 如果是这样,在这个简单的场景中实现此目的的首选方法是什么?

【问题讨论】:

  • “Entity Framework 生成的上下文对象不是线程安全的。” - 你为什么这么说?
  • 我指的是 MSDN:msdn.microsoft.com/en-us/library/…,上面写着“ObjectContext 类不是线程安全的。”
  • 是的,这就是我认为你的意思 - 上下文,而不是实体。这就是为什么你永远不应该为 OC 使用单例。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以使用工厂方法将您的 DbContext 作为工厂而不是实例本身注入,看看这个:https://github.com/vany0114/EF.DbContextFactory

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

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

    Ninject 有一个扩展,可以非常简单地做到这一点,只需调用方法kernel.AddDbContextFactory<YourContext>();,您还需要通过接收Func<YourContext> 来更改您的存储库

    【讨论】:

      【解决方案3】:

      在单个实体框架上下文上运行的一个线程不是线程安全的。

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

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

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

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

      【讨论】:

      • 谢谢。那么 SomeIntProperty 的实际值是在您执行 SubmitChanges() 时还是在什么时间读取的?我的意思是,如果第一个线程将值增加到 3,那么第二个线程是否可能仍会在某处缓存值 2,还是会当场检索该值?
      • 我忽略了您示例的几个重要方面。首先,您没有检索和实例化“SomeObject”的代码。因此,如图所示,代码将不起作用。上下文之间不共享缓存、缓冲区或锁。因此,每个线程及其上下文实例可以被认为与您认为进程在两台不同机器上运行的方式相同。所以你必须相应地处理数据库并发问题。
      • 您需要实现乐观并发或数据库事务来处理数据库并发问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多