IQueryable<EntityOne> query = entities.EntityOne
.Include(t => t.EntityRelated1)
.Include(t => t.EntityRelated2)
.AsQueryable();
在“查询”变量中生成的查询:
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]
之后,在C#代码上,这些是计数的结果:
var wrongCount = query.Count(); // Returns 295
var correctCount = query.AsEnumerable().Count(); // Returns 10
295计数是完整的EntityOne设置的寄存器数。 (错误的)
10次计数是内部加入后的理想计数。
在执行数据库IQueryable.Count()
之前,InnerJoin
听起来好像在计算。我不想生成IEnumerable
,因为我希望计数在Sql Server
上与内连接一起执行。
更新1
尝试手动执行内连接:
IQueryable<EntityOne> query2 = entities.EntityOne.Join(entities.EntityTwo,
eone=> eone.IdRelatedOne, en => en.Id,
(x, y) => x);
“query2”中生成的SQL代码是:
SELECT
[Extent1].[Id] AS [Id],
...
FROM [dbo].[EntityOne] AS [Extent1]
正如您所看到的,相关实体不包含在由linq Join语句强制的内部联接中。
更新2
我不知道它是否重要但是,EntityOne上的IdEntityRelated1是必需属性,加上它不是数据库上的外键,只是存储相关实体Id的Integer字段。 (我正在使用数据库优先的POCO课程)
我有另一个工作源,其中字段但它们是可空的整数而不是必需的。也许我不应该尝试做一个Include强制内部加入所需的关系?
答案 0 :(得分:1)
您具有必需的关联,但数据库中不存在预期的对象。
但是,让我们先看看EF做了什么。
在第一次计数 ...
中var wrongCount = query.Count();
... Include
被忽略。没有理由执行它们,因为EF已被告知被引用的对象(EntityRelated1
和EntityRelated2
是必需的,因此内连接应该找到相关的记录entities.EntityOne并跳过其余部分。Includes
只会使查询更加昂贵而且不会影响结果。
您可以通过监视为计数执行的SQL来检查。当你只看query
时,这不是SQL生成的!它可能只是归结为
SELECT COUNT(*) FROM [dbo].[EntityOne]
因此,第一个计数会返回数据库中所有EntityOne
个记录的正确计数。
对于第二次计数,您强制执行存储在query
变量中的整个查询,即您显示的SQL语句。然后在内存中计算其结果 - 并返回10
。这意味着具有内部联接的查询实际上返回10条记录。反过来,这只能意味着一件事:有285 EntityOne.IdRelatedOne
个值并不指向现有的EntityRelatedOne
记录。但是您根据需要映射了关联,因此EF生成内部联接。外连接也将返回295。
答案 1 :(得分:0)
#include <memory>
struct A
{
void foo(const int& i) { }
};
template <typename F, class ...Args>
void a_caller(A& a, F &&f, Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
int main()
{
int i = 42;
A a;
a_caller(a, &A::foo, i);
}
不是LINQ方法,是一个EntityFramework扩展,旨在进行急切加载而不是其他。 Include
s are lost if the query shape changes:
当您调用Include方法时,查询路径仅对返回的IQueryable T实例有效.Tu的IQueryable的其他实例和上下文本身不受影响。
具体而言,这意味着,例如Include
d Include
之上的聚合将会松开IQueryable<T>
(这正是您所看到的)。
请参阅Tip 22 - How to make Include really Include,IQueryable.Include() gets ignored,Include in following query does not include really等等。