使用 Entity Framework 获取记录计数会导致大量读取

Getting record counts with Entity Framework results in high number of reads

SQL 服务器 2016,Entity Framework .NET 4.6.2 上的 6.4

给定这两个表:

ParentTableid 列上的 ChildTable 之间存在一对多关系。

我想知道有多少“活动”子行,masterId 为 1。在 T-SQL

中足够简单
select count(1) 
from parentTable 
join childTable on parentTable.id = childTable.id
where masterId = 1 and isActive = 0

现在我想在 Entity Framework 中做到这一点。同样,语法很简单:

 var activeCount= db.childTable.Count(d => d.parentTable.masterId == 1 && !d.isActive);

两个 return 相同的计数,但是....这个 Entity Framework 调用使一些丑陋的 SQL 非常低效:

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM  [dbo].[childTable] AS [Extent1]
        INNER JOIN [dbo].[parentTable] AS [Extent2] ON [Extent1].[id] = [Extent2].[id]
        WHERE ([Extent2].[masterId] = @p__linq__0) AND ([Extent1].[isActive] <> 1)
    )  AS [GroupBy1]',N'@p__linq__0 int',@p__linq__0=1

区别在于简单的 count(1) 语句有 10 次逻辑读取,而 Entity Framework 语句有 9200 次逻辑读取。我弄乱了 EF 的不同语法,此时它们都创建了相同的 T-SQL.

我是否在 EF 中遗漏了一些东西来有效地进行这个简单的计数?

所有三个查询都要求不同的东西。

第一个查询不包含 childTable.isActive = 1.

条件

LINQ 表达式确实包含该条件。这是唯一似乎符合您所述意图的查询,“计算有多少个‘活动’子行,masterId 为 1”。

生成的SQL 具有相反 isActive 条件:[Extent1].[isActive] <> 1。它似乎也在寻找不同的 masterid.

虽然 Linq to SQL 肯定会产生一些可怕的 SQL,但这不是这里的问题。生成的 sql 仅在使用冗长的别名和丑陋的参数名称的意义上是丑陋的。但不平等以及不同 masterid 是问题所在。

根据您的意图仔细检查您的代码,并确保您是在同类比较。