ASPNet Entity Framework 6 - EF6,在同一个工作单元中混合异步和同步
Posted
技术标签:
【中文标题】ASPNet Entity Framework 6 - EF6,在同一个工作单元中混合异步和同步【英文标题】:ASPNet Entity Framework 6 - EF6, mixing async and sync in the same unit of work 【发布时间】:2020-01-27 16:17:33 【问题描述】:我今天遇到了几行代码,归结为如下:
using (var db = new AppDbContext())
var foo = await db.Foos
.Where(m => m.Name == "BuzzBaz" )
.FirstAsync();
foo.Name = "Quxx";
db.SaveChanges();
请注意,选择查询是 async
,但对 SaveChanges() 的调用不是。是同步的!
这可能会造成任何问题吗?我应该重构它以使用db.SaveChangesAsync();
并且一切都很好吗?或者也许只是调用First()
而不是FirstAsync()
?或者它可能是无害的并且可能对整体系统性能有一些好处?
我发现一些文档让我认为完全删除 async
可能是一个不错的选择。 https://docs.microsoft.com/en-us/ef/ef6/fundamentals/async
在大多数使用异步的应用程序中没有明显的好处,甚至可能是有害的。在提交之前使用测试、分析和常识来衡量异步在您的特定场景中的影响。
【问题讨论】:
【参考方案1】:您的代码实际上是“正确的”,这意味着它没有根本缺陷。
让我们分析一下发生了什么,以及我的 2 美分:
查询数据库时(FirstAsync
),使用await
表示指令将按顺序执行,但线程不会被阻塞(异步调用),可以用于其他事情.这可能是一件好事,如果这是一个服务器应用程序,您可能希望您的线程能够在等待数据库响应时处理其他请求。
但是,使用非异步 SaveChanges
会阻塞线程。这本身不是错误,但由于它也是对 db 的 I/O 操作,它可能会阻塞线程一段时间。如果你也在这里await
使用异步版本,它确实看起来更“一致”。
这是个问题吗?这取决于。您的应用程序是否被大量使用?您的用户在重负载时是否遇到一些低反应?那么在这种情况下,在保存时使用异步可能是一个潜在的改进。
否则,正如链接的 MSDN 文章中所建议的那样,在您知道它有影响之前,我的建议是不要太担心。
混合使用本身不是问题。
就个人而言,我也会选择异步 SaveChanges,以保持一致性并想象 DB 写入是一些可能很慢的 I/O 操作。
如果是桌面应用程序,请确保您没有阻塞 UI 线程。
【讨论】:
使用await
表示语句将异步执行,执行流程将返回给调用者。线程是否阻塞取决于调用者。
@PauloMorgado 我不确定要使用正确的词,但为了让其他读者清楚:async Task MainFunction() Console.WriteLine("before"); await Foo(); Console.WriteLine("after")
和 async Task Foo() // long processing during several seconds ... and then : Console.WriteLine("processed!"):
将可靠地导致输出:“之前” ,“处理!”,“之后”。执行流程对我来说看起来很“同步”,await
所做的(使异步调用看起来与执行流程同步)。
你不是把顺序和同步搞混了吗?
@PauloMorgado 最有可能!谢谢你的话,我会编辑我的答案【参考方案2】:
除了编码一致性(这非常重要)之外,请考虑以下几点:
-
这是一个 DAL 库吗?你确定谁会使用它,你确定代码的可重用性永远不会成为问题吗?
如果答案是可能的,请坚持使用异步。前端 UI 将在保存期间被阻止,使其无响应。 Web API 使用 IO 线程来实现更好的线程管理:Simple description of worker and I/O threads in .NET
如果它是一个库,请确保将ConfigureAwait(false)
用于所有异步函数调用。
-
即使使用 await,调用也是异步的,就在另一个线程上运行的 rubbing 而言,而原来的线程正在等待。大多数情况下,这作为性能可以忽略不计,但为什么不呢?
我通常将所有内容都设为异步,如果需要同步实现,我更喜欢使用同步版本制作代码副本。
【讨论】:
以上是关于ASPNet Entity Framework 6 - EF6,在同一个工作单元中混合异步和同步的主要内容,如果未能解决你的问题,请参考以下文章
如何告诉 Entity Framework 我的 ID 列是自动递增的(AspNet Core 2.0 + PostgreSQL)?
在 Entity Framework 7 RC 1 和 ASP.NET MVC 6 中播种初始数据 [重复]
向数据库添加新表后如何更新 Entity Framework Core