【问题标题】:Thread safe Entity Framework 6线程安全的实体框架 6
【发布时间】:2013-11-03 15:07:00
【问题描述】:

刚刚开始测试 EF6 及其异步功能。 当我意识到它们不是线程安全的时,我很惊讶。我有点假设这就是重点。

多年来,我已经拥有自己的基于 Task 的扩展方法,但我一直在等待 EF 让它们成为线程安全的。

至少我的基于任务的功能locked 不会相互干扰。 EF6 甚至没有走那么远。但主要问题是我的代码与他们的代码共享。即尝试发出异步查询,然后在它完成之前尝试访问触发延迟加载的导航属性(在同一上下文中预加载的完全独立的实体上)。这可以由 UI 触发,也可以由即时函数之外的其他代码触发,也可以由许多其他场景触发。

据我所知。 dbContext 中仅有的两个共享(实体之间)可变资源是连接和更改跟踪(缓存)。如果我们可以在这些功能周围添加锁定,那么我们将拥有一个线程安全的上下文。

我们甚至可以分两个阶段完成。如果我们可以实现一个提供者来锁定用于查询数据库的一个集中功能。然后任何未跟踪的查询 - 通过返回非实体(匿名)对象或通过调用 AsNoTracking() - 将是线程安全的,并且即使在另一个线程可能要求延迟加载的对象时也可以安全地使用 Async 函数调用。

我们的可扩展性不会比现在更糟,因为我们现在必须为每个线程使用一个上下文,如果您尝试跳过甚至一个 await 以引入一些并行性或正在工作,即使是 Async 函数也不适用在事件系统(如 wpf)中,一旦等待的函数与任务一起返回,可能会触发。

所以我的问题是。有没有人实现过这样的提供者。或者有人愿意和我一起工作吗?

【问题讨论】:

  • 有趣的是,EF6 不仅线程不安全,而且是线程化的。 EF6 和Async 函数的重点不是线程。其实asyncawait不是线程框架。它是一个async 框架。您可以编写单线程异步应用程序,实际上这是您在node.js 中唯一可以做的事情。
  • 我相信使用 EF6 async 时的一般指导是完全禁用延迟加载。否则,您将混合使用异步代码和阻塞代码,这将始终存在行为怪癖。
  • @StephenCleary 由于当前的实施,这可能是一般指导。但是,如果有人要在 locked 围绕数据库访问的提供商上工作。然后我们就可以同时使用两者了。
  • @Rabbi:关键是你不会想要。延迟加载将不必要地阻塞异步操作上的线程。如果您 Include 相关实体或执行单独的(异步)后续请求,您的代码将完全异步。
  • @Rabbi:大部分时间异步Tasks 是基于(逻辑)事件,not 线程。在 EF6 中尤其如此。

标签: multithreading entity-framework task-parallel-library entity-framework-6


【解决方案1】:

我认为您正面临架构问题。您描述的是一个 UI 直接使用 EF 对象的应用程序,它打破了“关注点分离”范式。

在我这边,我在模型层上使用自定义线程安全缓存,让一切都发生在模型层上。我使用众所周知的 AsyncLock 在我的缓存上实现了线程安全。

DbContext 对象,并且每个 EF CRUD 相关操作都有一个非常有限的生命周期。每个 CRUD 操作实例化它自己的 DbContext,并将模型对象返回到缓存,然后,上下文被垃圾收集。我的应用程序使用缓存作为抽象层,而缓存使用 EF 作为 DB 抽象层。

例如,探索对象上的附加属性,是通过在模型层上实现自定义方法来完成的,该方法以对象 ID 作为参数,并将相关对象的列表返回到缓存中。 UI 询问 Cache,然后 Cache 询问 EF,一旦可用,对缓存的调用会将对象返回给 UI。就这么简单。

EntityFramework 并非设计为线程安全的,因此无法以多线程方式使用它。 (EF thread safety)

您必须构建一个可以以多线程方式访问的模型层,而不是并行访问您的 DbContext。您的模型可以对您的 DB 进行多次并行调用,但请记住,每个调用都必须实例化并保持其自己的 DbContext。在每次调用结束时,必须释放相关的 DbContext。

DbContext 实例化速度非常快,唯一的缺点是网络延迟。这就是为什么内存缓存是个好主意。

【讨论】:

  • 如果我对每一个可以通过更频繁地实例化 DbContexts 来解决的 EF 问题都有一分钱......
猜你喜欢
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多