Entity Framework生成的上下文对象不是线程安全的。
如果我使用两个独立的实体上下文,每个线程一个(并在每个线程上调用SaveChanges()
),这会是线程安全的吗?
// this method is called from several threads concurrently
public void IncrementProperty()
{
var context = new MyEntities();
context.SomeObject.SomeIntProperty++;
context.SaveChanges();
}
我相信实体框架上下文实现了某种“计数器”变量,它跟踪上下文中的当前值是否是新鲜的。
答案 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>
来更改存储库