我一直在努力将 ASP.NET MVC 仪表板页面转换为使用异步实体框架方法,并且遇到了一个问题,有时调用会无限期挂起而没有错误或挂起一段时间 > 1 分钟并解决. 这种行为是零星的,我还没有找到复制它的方法。这是我的 EF 电话之一,当然是经过消毒的。
注意:sql和parameters对象在上面定义。 sql是一个字符串形式的查询。
using (var context = new BaseDbContext())
{
return await context.Database.SqlQuery<MyViewModel>(sql, parameters.ToArray()).ToListAsync();
}
然而,这不是唯一会挂起的查询。有时其他查询会挂起,有些是用 linq to sql 编写的,有些则使用上面的实际 sql 查询。
重要笔记
- 我一直使用 async/await 到我的控制器,包括我的控制器方法本身。
- 有时一切都运行良好——所有异步调用都正常运行,并且一切都在几秒钟内加载完毕。
- “挂起”行为是零星的。有时它不会在几个小时内发生,有时它会在我每次启动应用程序时发生。
编辑
评论中的安德烈斯建议可能至少为我指明了正确的方向。在几个小时没有问题后挂断时,我设法赶上了该程序。SQL Profiler 发现了几个RPC:Completed非常简单的选择需要 15-65 秒以上的事件(在 SSMS 中运行时需要几分之一秒才能完成)。所有这些都相当接近。
我已经清理并将正在运行的 SQL 放在下面,并添加了开始/结束时间以添加上下文。
exec sp_executesql N'SELECT * FROM Reports.dbo.Customers WHERE Date = @Par1',N'@Par1 datetime',@Par1='2020-07-20 00:00:00'
开始时间:14:22:08.597
结束时间:14:22:23.197
exec sp_executesql N'SELECT * FROM Reports.dbo.Customers WHERE Date = @Par1',N'@Par1 datetime',@Par1='2019-07-20 00:00:00'
开始时间:14:22:23.267
结束时间:14:22:37.357
exec sp_executesql N'SELECT * FROM Reports.dbo.Policies WHERE Date = @Par1 OR Date = @Par2',N'@Par1 datetime,@Par2 datetime',@Par1='2020-07-20 00:00:00',@Par2='2020-06-20 00:00:00'
开始时间:14:22:38.200
结束时间:14:23:42.333
exec sp_executesql N'SELECT * FROM Reports.dbo.Policies WHERE Date = @Par1',N'@Par1 datetime',@Par1='2020-07-20 00:00:00'
开始时间:14:23:46.863
结束时间:14:23:58.773
还有一个更难清理的 Entity Framework 查询,耗时约 6 秒,以及Audit Logout在所有内容中间出现的可疑事件。该事件的开始时间为 14:18:25.753,结束时间为 14:23:25.770。
虽然我在解释这些结果方面没有大量知识,但在我看来,由于 MVC 应用程序中的所有内容都是异步/等待,问题可能是多个查询在相似的时间访问同一个数据库表?在将仪表板转换为异步/等待之前,我不相信这实际上会挂起。
编辑 2 基于 Andres 的答案以及我在 SQL Profiler 中向我的跟踪添加附加信息后学到的知识(请参阅下面该答案下方的评论),似乎表锁定是罪魁祸首——但是我正在努力寻找信息关于如何解决这个问题。我猜我们可能不得不回滚到对所有内容使用同步数据库调用而不是异步?

