2010-12-15 108 views
28

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

如果我使用两个单独的实体上下文,每个线程一个(并且每个线程都调用SaveChanges())会怎么样 - 这是线程安全的吗?

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

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

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

  1. 上面的代码 - 从不同的线程调用 - 我仍然需要锁定增量/ savechanges吗?
  2. 如果是这样,那么在这个简单的场景中完成此操作的首选方法是什么?
+0

*“的上下文对象所产生的改变你的资料库实体框架不是线程安全的。“* - 你为什么这么说? – RPM1984 2010-12-15 22:42:31

+0

我指的是MSDN:http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx它说“ObjectContext类不是线程安全的。” – Harper 2010-12-15 22:49:57

+0

是的,这就是我认为你的意思 - 背景,而不是实体。这就是为什么你不应该为OC使用单身人士。 – RPM1984 2010-12-16 00:36:16

回答

31

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

每个线程的一个单独的上下文实例是线程安全的。只要每个执行线程都有自己的EF上下文实例,你就会好起来的。

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

不过,我建议实施一个“使用”块这个如下:

​​
+0

谢谢。那么当您执行SubmitChanges()或什么时候会读取SomeIntProperty的实际值?我的意思是,如果第一个线程将值递增到3,第二个线程是否仍然可能将值2缓存到某个位置,或者它会在现场检索值? – Harper 2010-12-15 23:27:21

+0

我忽略了你的例子的几个重要方面。首先,你没有检索和实例'SomeObject'的代码。所示的代码将无法工作。上下文之间不共享缓存,缓存或锁定。因此,每个线程及其上下文实例都可以被认为与您认为该进程在两台不同机器上运行的方式相同。所以你必须相应地处理数据库并发问题。 – 2010-12-16 06:28:05

+1

您需要实施乐观并发或数据库事务来处理数据库并发问题。 – 2010-12-16 06:36:20

0

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