3

我想在单个查询中检索一组对象 ( A) 和一些相关对象 ( )。B没有导航属性AB所以我相信我需要使用以下语法:

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

4

1 回答 1

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
             });
于 2012-07-21T16:45:10.570 回答