为什么EF Core会额外执行SELECT COUNT(*)?关联Telerik KENDO ToDataSourceResult问题
EF Core读取实体额外生成COUNT(*)查询的解决方案
问题现象
开发基于EF Core 2.1的小型Web应用时,发现每次读取实体都会额外执行一次COUNT(*)查询,示例查询代码如下:
var analysis = _context.Analyses.Where(p => p.CommitmentId == commitmentId).AsNoTracking();
VS2019输出窗口生成的执行日志如下:
SELECT COUNT(*) FROM [ANALYSES] AS [p] WHERE [p].[CommitmentId] = @__commitmentId_0 Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (36ms) [Parameters=[@__commitmentId_0='?' (DbType = Int32), @__p_1='?' (DbType = Int32), @__p_2='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] SELECT [p].[Id], [p].[Amount] [...] FROM [ANALYSES] AS [p] WHERE [p].[CommitmentId] = @__commitmentId_0 ORDER BY (SELECT 1)
尝试多种方案都无法禁用该额外查询,需要找到对应的解决方法。
原因分析及解决方案
原因
上述的查询代码本身并不会触发SQL执行,多余的COUNT查询是后续调用ToDataSourceResult方法触发的,对应的业务代码如下:
return Json(analysis.ToDataSourceResult(request));
该额外COUNT查询属于Telerik组件ToDataSourceResult方法的默认行为,和EF Core本身无关:ToDataSourceResult会对传入的IQueryable对象自动执行计数查询,用于前端组件的分页、总条数统计等功能。
解决方案
只需要在EF Core查询语句末尾调用ToList(),提前将查询结果加载到内存中,再传入ToDataSourceResult方法即可,修改后的查询代码如下:
var analysis = _context.Analyses.Where(p => p.CommitmentId == commitmentId).AsNoTracking().ToList();
修改后ToDataSourceResult会直接操作内存中的集合,不会再触发额外的COUNT()查询。
内容的提问来源于stack exchange,提问作者TheSQLDeveloper
相关产品推荐
相关产品推荐

