我刚开始测试EF6及其异步函数,但惊讶地发现它们不是线程安全的,我原以为这正是它们的目的。
我已经拥有自己的Task
扩展方法多年了,但我期待EF能使它们变得线程安全。
至少我的基于Task的函数使用了lock
来避免相互干扰。但EF6甚至没有这么做。但主要问题与我的代码共享。例如,尝试发出异步查询,然后在其完成之前尝试访问导航属性(在同一上下文中的预加载完全分离的实体上触发惰性加载)。这可能由UI触发,也可能由其他代码在当前函数之外触发,或者由数十种其他情况触发。
据我所知,在dbContext中仅有两个可变资源(在实体之间共享)是连接和更改跟踪(缓存)。如果我们可以在这些功能周围添加锁定,则我们将拥有线程安全的上下文。
我们甚至可以分两个阶段进行。如果我们可以实现一个提供程序来锁定用于查询数据库的一个集中的函数。那么任何非跟踪查询-通过返回非实体(匿名)对象或调用AsNoTracking()-都将是线程安全的,并且即使另一个线程可能正在请求一个惰性加载的对象,也可以在异步函数中调用它们。
我们的可扩展性不会比现在使用每个线程一个上下文更差,即使您尝试跳过一个await以引入一些并行性或在事件系统(如wpf)中工作,该系统可能会在等待函数返回任务后触发。
所以我的问题是,有人实现了这样的提供程序吗?或者有谁愿意与我合作实现它?
async
时,一般的指导是完全禁用延迟加载。否则,您将拥有异步和阻塞代码的混合,这将始终具有行为怪异性。 - Stephen Clearylock
的提供程序,那么我们将能够同时使用两者。 - RabbiInclude
相关实体,要么执行单独的(异步)后续请求,你的代码就完全是异步的了。 - Stephen Cleary