使用 Entity Framework 获取记录计数会导致大量读取
Getting record counts with Entity Framework results in high number of reads
SQL 服务器 2016,Entity Framework .NET 4.6.2 上的 6.4
给定这两个表:
- ParentTable (int masterId, int id)
- ChildTable (int id, bit isActive)
ParentTable
和 id
列上的 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
是问题所在。
根据您的意图仔细检查您的代码,并确保您是在同类比较。
SQL 服务器 2016,Entity Framework .NET 4.6.2 上的 6.4
给定这两个表:
- ParentTable (int masterId, int id)
- ChildTable (int id, bit isActive)
ParentTable
和 id
列上的 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
是问题所在。
根据您的意图仔细检查您的代码,并确保您是在同类比较。