[英]IQueryable Count() method issue with Inner Join created by .Include() related entities
IQueryable<EntityOne> query = entities.EntityOne
.Include(t => t.EntityRelated1)
.Include(t => t.EntityRelated2)
.AsQueryable();
The query generated in "query" variable : 在“查询”变量中生成的查询:
SELECT
[Extent1].[Id] AS [IdEntityOne],
...
[Extent2].[Id] AS [IdEntityRelatedOne],
...
[Extent3].[Id] AS [IdEntityRelatedTwo],
...
FROM [dbo].[EntityOne] AS [Extent1]
INNER JOIN [dbo].[EntityRelatedOne] AS [Extent2]
ON [Extent1].[IdRelatedOne] = [Extent2].[Id]
INNER JOIN [dbo].[EntityRelatedTwo] AS [Extent3]
ON [Extent1].[IdRelatedTwo] = [Extent3].[Id]
After that, on C# code those are the result of counting: 之后,在C#代码上,这些是计数的结果:
var wrongCount = query.Count(); // Returns 295
var correctCount = query.AsEnumerable().Count(); // Returns 10
The 295 count is the full EntityOne set numbers of registers. 295个计数是EntityOne集的全部寄存器数。 (wrong)
(错误)
The 10 Count is the desired count after Inner Join. 10计数是内部加入后所需的计数。
It sounds like the IQueryable.Count()
is counting before executing the InnerJoin
on database. 听起来
IQueryable.Count()
正在对数据库执行InnerJoin
之前正在计数。 I don't want to generate the IEnumerable
since I hope the count to be executed on Sql Server
together with the inner join. 我不想生成
IEnumerable
因为我希望该计数与内部Sql Server
一起在Sql Server
上执行。
UPDATE 1 更新1
Trying to manually execute the inner join: 尝试手动执行内部联接:
IQueryable<EntityOne> query2 = entities.EntityOne.Join(entities.EntityTwo,
eone=> eone.IdRelatedOne, en => en.Id,
(x, y) => x);
The SQL code generated in "query2" is : 在“ query2”中生成的SQL代码是:
SELECT
[Extent1].[Id] AS [Id],
...
FROM [dbo].[EntityOne] AS [Extent1]
As you can see, the related entity is not included on Inner Join forced by linq Join statement. 如您所见,在linq Join语句强制的内部联接中不包含相关实体。
Update 2 更新2
I dont know if it matters but, the IdEntityRelated1 on EntityOne is a required property, plus its not a foreign key on database, just a Integer field that stores the Id of the related entity. 我不知道这是否重要,但是EntityOne上的IdEntityRelated1是必需属性,加上它不是数据库上的外键,只是存储相关实体ID的Integer字段。 (Im working with POCO classes with Database First)
(我正在与数据库优先一起使用POCO类)
I have another working sources where fields but they're nullable integers instead of required. 我在字段中有另一个工作源,但它们是可为空的整数,而不是必需的。 Maybe should I not try to do an Include to force Inner Join between required relationships?
也许我不应该尝试在所需关系之间进行包含以强制内部联接吗?
You have a required association, but the expected objects are not present in the database. 您具有必需的关联,但是数据库中不存在预期的对象。
But let's first see what EF does. 但首先让我们看看EF的作用。
In the first count ... 第一次 ...
var wrongCount = query.Count();
...the Include
s are ignored. ...
Include
被忽略。 There's no reason to execute them because EF has been told that the referred objects ( EntityRelated1
and EntityRelated2
are mandatory, so inner joins are expected to find the related records . If they do, EF figures it may as well just count entities.EntityOne
and skip the rest. The Includes
are only going to make the query more expensive and they don't affect the result. 没有理由执行它们,因为已经告知EF所引用的对象(
EntityRelated1
和EntityRelated2
是强制性的,因此内部联接应查找到相关记录 。如果这样做,EF可能认为它也可以只对entities.EntityOne
计数。 Includes
只会使查询更昂贵,并且不会影响结果。
You can check that by monitoring the SQL that's executed for the count. 您可以通过监视为计数而执行的SQL进行检查。 That's not the SQL generated when you look at
query
only! 仅查看
query
时,这不是生成的SQL! It's probably something that simply boils down to 大概可以归结为
SELECT COUNT(*) FROM [dbo].[EntityOne]
So the first count returns a correct count of all EntityOne
records in the database. 因此,第一个计数返回数据库中所有
EntityOne
记录的正确计数。
For the second count you force execution of the entire query that's stored in the query
variable, the SQL statement that you show. 对于第二个计数,您强制执行存储在
query
变量(显示的SQL语句)中的整个查询。 Then you count its results in memory – and it returns 10
. 然后,将其结果计数在内存中-并返回
10
。 This means that the query with the inner joins does actually return 10 records. 这意味着带有内部联接的查询实际上返回了10条记录。 That, in turn, can only mean one thing: there are 285
EntityOne.IdRelatedOne
values that don't point to an existing EntityRelatedOne
record. 反过来,这仅意味着一件事:有285个
EntityOne.IdRelatedOne
值不指向现有的EntityRelatedOne
记录。 But you mapped the association as required, so EF generates an inner join. 但是您根据需要映射了关联,所以EF生成了一个内部联接。 An outer join would also return 295.
外部联接也将返回295。
Include
is not a LINQ method proper, is an EntityFramework extension designed to do eager loading and not much else. Include
不是适合的LINQ方法,而是EntityFramework扩展,旨在进行急切的加载,仅此而已。 Include
s are lost if the query shape changes : 如果查询形状更改,则
Include
会丢失 :
When you call the Include method, the query path is only valid on the returned instance of the IQueryable of T. Other instances of IQueryable of T and the context itself are not affected.
当您调用Include方法时,查询路径仅在T的IQueryable实例的返回实例上有效。T的IQueryable的其他实例和上下文本身均不受影响。
Specifically this means that, for instance aggregates on top of the Include
d IQueryable<T>
are going to loose the Include
(which is exactly what you see). 具体来说,这意味着,例如,在
Include
d IQueryable<T>
之上的聚合将失去Include
(正是您所看到的)。
See Tip 22 - How to make Include really Include , IQueryable.Include() gets ignored , Include in following query does not include really and many more. 请参见技巧22-如何使Include真正包含 , IQueryable.Include()被忽略 , 以下查询中的Include并不包含真正的更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.