【发布时间】:2019-04-13 12:59:13
【问题描述】:
原本应该是一项相对简单的任务,现在却变成了一个令人惊讶的复杂问题。以至于我开始认为我的方法可能超出了 Linq 的能力范围。
我要做的是拼凑一个 Linq 查询,然后调用 .Include() 以便从多个子实体中提取值。例如,假设我有这些实体:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public ISet<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
public string Name { get; set; }
}
假设我要执行查询以从Parent 检索记录,其中Name 是某个值,Location 是某个其他值,然后还包括Child 记录。但无论出于何种原因,我都不知道Name 和Location 同时的查询值,所以我必须采用两个单独的可查询对象并加入它们,例如:
MyDbContext C = new MyDbContext();
var queryOne = C.Parent.Where(p => p.Name == myName);
var queryTwo = C.Parent.Where(p => p.Location == myLocation);
var finalQuery = queryOne.Intersect(queryTwo);
效果很好,产生的结果就像我刚刚做的一样:
var query = C.Parent.Where(p => p.Name == myName && p.Location = myLocation);
同样,我可以:
var finalQuery = queryOne.Union(queryTwo);
给我的结果就像我有:
var query = C.Parent.Where(p => p.Name == myName || p.Location = myLocation);
然而,一旦应用了Intersect() 或Union(),我不能做的就是使用Include() 映射Child,如下所示:
finalQuery.Include(p => p.Children);
此代码将编译,但产生如下结果:
- 在
Union()的情况下,将生成结果集,但不会枚举Child实体。 - 在
Intersect()的情况下,尝试应用Include()时会生成运行时错误,如下所示:
类型的表达 'System.Collections.Generic.IEnumerable`1[Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject]' 不能用于类型参数 'System.Collections.Generic.IEnumerable`1[System.Object]' 的方法 'System.Collections.Generic.IEnumerable`1[System.Object] 相交[对象](System.Collections.Generic.IEnumerable`1[System.Object], System.Collections.Generic.IEnumerable`1[System.Object])'
让我感到困惑的是,这段代码会完全按预期工作:
var query = C.Parent.Where(p => p.Name == myName).Where(p => p.Location == myLocation);
query.Include(p => p.Children);
即,获得所需的结果,包括枚举的Child 实体。
【问题讨论】:
-
那你为什么不直接使用
var query = C.Parent.Where(p => p.Name == myName); query = query.Where(p => p.Location == myLocation); query = query.Include(p => p.Children);呢?有没有你没有的东西? -
嗯,这将适用于加入查询的 OR(联合)条件,但不适用于 AND(相交)。
-
恰恰相反。对
Where的两次调用对最终查询执行AND -
对,这就是我的意思...适用于 AND 条件,但不适用于 OR。我两个都需要。
-
在某些时候你有两种价值观,不是吗?等到你这样做了。
标签: c# linq entity-framework-core entity-framework-core-2.1