实体框架:如何防止多个线程访问dbcontext?

时间:2016-06-27 12:14:13

标签: c# .net multithreading entity-framework

我正在使用Async并等待多线程。

如果我在单线程上使用Async并等待它可以正常工作但是当我使用多个线程时,它会出现错误,我试图访问具有多个线程的dbcontext。

我知道我不能这样做。但现在我想要有一个调度程序,它将调度dbcontext对每个线程的访问。

如何编写此类调度程序/互斥锁或其他解决此问题的方法。

2 个答案:

答案 0 :(得分:3)

您绝对可以将EF与async/await一起使用,但you can't perform two operations at once on the same context

就性能而言,it's actually faster to create two contexts看起来是您使用async/await的原因。

对于此示例,我建议您为每个CallToDbOps()创建两个单独的上下文。

答案 1 :(得分:0)

这不是帮助[用户] ...

的信息答案

Have a read of this bloghave a read of this article about Entity Framework specifications for its async pattern support

DbContext不是线程安全的

您绝不能同时从多个线程访问DbContext派生的实例。这可能导致在同一数据库连接上同时发送多个查询。它还会破坏DbContext维护的第一级缓存,以提供其身份映射,更改跟踪和工作单元功能。

在多线程应用程序中,您必须在每个线程中创建和使用DbContext派生类的单独实例。

因此,如果DbContext不是线程安全的,那么它如何支持EF6引入的异步查询功能呢?只需阻止在任何给定时间执行多个异步操作(如实体框架规范中针对其异步模式支持所述)。如果您尝试并行执行同一个DbContext实例上的多个操作,例如通过DbSet.ToListAsync()方法并行启动多个SELECT查询,您将收到带有以下消息的NotSupportedException:

  

在上一次异步操作完成之前,在此上下文中启动了第二个操作。使用'等待'确保在调用此上下文中的另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

实体框架的异步功能可以支持异步编程模型,而不是支持并行性。

取自EF文章:

" 主题安全

虽然线程安全会使异步更有用,但它是一个正交特征。目前还不清楚我们是否可以在最常见的情况下实现对它的支持,因为EF与用户代码组成的图形交互以维持状态,并且没有简单的方法来确保此代码也是线程安全的。

目前,EF将检测开发人员是否一次尝试执行两次异步操作并抛出。"