我想在单个查询中检索一组对象(A
)和一些相关对象(B
)。 A
和B
上没有导航属性,所以我相信我需要使用这种语法:
select a from db.As where a.Id = x select new AndBHolder
{
A = a,
Bs = select b from db.Bs where b.ASomeId == A.SomeId select b
}
我不确定这是否是最佳方式,但它确实有效。但是,我现在需要包含B
的属性(Cs
列表)。我没想到它会起作用,但我试过了:
select a from db.As where a.Id = x select new AndBHolder
{
A = a,
Bs = select b from db.Bs.Include("Cs") where b.ASomeId == A.SomeId select b
}
哪个失败,“方法...在类型上声明包含...不能使用类型的实例调用...”。接下来我想我会在投影中尝试投影:
select a from db.As where a.Id = x select new AndBHolder
{
A = a,
Bs = select b from db.Bs where b.ASomeId == A.SomeId select new B
{
Id = b.Id,
// ...
Cs = select c from db.Cs where c.BId == b.Id select c
}
}
失败的“实体或复杂类型'B
'无法在LINQ to Entities查询中构造”因为您不允许投影到映射对象中。那么如何在填充Bs
的情况下检索Cs
,或者不支持二级包含?我是否只需要对数据库进行两次调用,一次是检索As,另一次是使用Bs
检索Cs
?
答案 0 :(得分:3)
如果您使用select new
投影,则无法再使用Include
,它将被忽略。相反,您必须将相关实体添加到投影数据中,例如:
var query = from a in db.As
join b in db.Bs on a.SomeId equals b.ASomeId into bGroup
where a.Id = x
select new AndBHolder
{
A = a,
Bs = bGroup, // Bs must be of type IEnumerable<B>
Cs = bGroup.SelectMany(bg => bg.Cs) // Cs is IEnumerable<C>
};
如果B
和C
之间的关系是一对多(不是多对多),EF应该在每个加载的Cs
中填充B
集合自动(称为“关系修正”),这意味着在从数据库加载数据后,您可以从投影中丢弃Cs
。要将它们组合在一起,您可以尝试编写查询,如下所示:
var query = (from a in db.As
join b in db.Bs on a.SomeId equals b.ASomeId into bGroup
where a.Id = x
select new
{
A = a,
Bs = bGroup,
Cs = bGroup.SelectMany(bg => bg.Cs)
})
.AsEnumerable() // DB query gets executed here
.Select(y => new AndBHolder
{
A = y.A,
Bs = y.Bs // the Cs in every B should be populated here
});