【发布时间】:2020-11-09 18:33:33
【问题描述】:
我一直致力于将 ASP.NET MVC 仪表板页面转换为使用异步实体框架方法,但遇到了一个问题,有时调用会无限期挂起并出现 no 错误或挂起持续时间 > 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 直到我的控制器,包括我的控制器方法本身。
- 有时一切都运行良好 - 所有异步调用都正常运行,一切都在几秒钟内加载完毕。
- “挂起”行为是偶发的。有时它不会在几个小时内发生,有时它会在我每次启动应用程序时发生。
编辑
来自 cmets 的 Andres 的建议可能为我指明了正确的方向,至少可以看看。在几个小时没有问题后挂断时,我设法赶上了该程序。 SQL Profiler 发现了几个RPC:Completed 事件,这些事件对于非常简单的选择(在 SSMS 中运行时需要几分之一秒才能完成)花费了 15-65 秒以上。所有这些都相当接近。
我已经清理并将正在运行的 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 应用程序中的所有内容都是异步/等待,因此问题可能是多个查询在相似的时间访问同一个数据库表?在将仪表板转换为 async/await 之前,我不相信这实际上会挂起。
编辑 2 根据 Andres 的回答以及我在 SQL Profiler 中向我的跟踪添加附加信息后所学到的知识(请参阅下面该答案下方的评论),似乎表锁定是罪魁祸首——但是我正在努力寻找有关如何解决这个问题。我猜我们可能不得不回滚到对所有内容使用同步数据库调用而不是异步?
【问题讨论】:
-
我强烈建议您使用 SQL Server Profiler 来跟踪查询。也许在数据库级别有一些阻塞。你知道怎么用吗?
-
试试
..ConfigureAwait(false) -
会试试这个建议@Nick。需要我一点时间,因为我将不得不将它添加到整个班级,但一旦我做出改变,我会更新你。
-
@Andres 我没有,但我的经理可能会。如果尼克的建议不起作用,我将与他联系以分析查询。
-
@Nick 为耽搁道歉,我被拉去开会。我已将 .ConfigureAwait(false) 添加到存储库中的所有调用中,但是此问题仍在继续发生。我成功地加载了仪表板,然后我在帖子中遇到了 EF 调用挂起,花了大约 3 分钟来解决。
标签: c# asp.net-mvc entity-framework async-await