过滤Entity Framework查询中的"包含"表

Joe*_*nos 17 .net c# linq entity-framework

这适用于.NET 3.5的Entity Framework:

我需要查询一个表并包含一对多关系的"多"表的集合.我试图过滤该集合作为查询的一部分 - 我对Entity Framework很新,而且我很难搞清楚它.

简化示例:作者拥有Books,而Book拥有IsFiction专栏.我想要一个过滤的作者列表,以及所有小说书籍.

没有过滤器,很容易:

var q = from a in db.Authors.Include("Books")
        where a.BirthYear > 1900
        select a;
Run Code Online (Sandbox Code Playgroud)

我可以在事后过滤,例如:

var fictionBooks = a.Books.Where(b => b.IsFiction);
Run Code Online (Sandbox Code Playgroud)

但问题是原始查询已经运行,并包含那些结果,这是不必要的数据库处理.

我可以单独查询,例如:

var q = from a in db.Authors where a.BirthYear > 1900 select a;
foreach (var a in q)
{
    var books = from b in db.Books 
                where ((b.Author.Id == a.Id) && (b.IsFiction))
                select b;
}
Run Code Online (Sandbox Code Playgroud)

但当然这是每个作者的一个电话,我也想避免.

我可以倒退,比如:

var allBooks = from b in db.Books.Include("Author")
               where b.IsFiction
               select b;
Run Code Online (Sandbox Code Playgroud)

但后来我回到原来的问题,除了现在在作者方而不是书方.

必须有一个包含所有内容的解决方案 - 我可以很容易地在SQL中完成它:

select * from author a
left join book b on a.id = b.author_id and b.is_fiction = 1
where a.birth_year > 1900
Run Code Online (Sandbox Code Playgroud)

有什么建议?

Tim*_*mwi 14

前进方式:

var q = from a in db.Authors.Include("Books")
        where a.BirthYear > 1900
        select new {
            Author = a,
            FictionBooks = a.Books.Where(b => b.IsFiction)
        };
Run Code Online (Sandbox Code Playgroud)

另一种方法,源自问题底部的SQL:

var q = from a in db.Authors
        from b in db.Books.Include("Author")
        where a.BirthYear > 1900 && b.IsFiction && a.Id == b.Author.Id
        select new { Author = a, Book = b };
Run Code Online (Sandbox Code Playgroud)

这两者之间的主要区别在于,第一个基本上会给你一组作者以及每个作者的小说书清单(可能是空的); 而第二个会给你一组作者/书籍对(因此它不会返回任何没有小说书籍的作者).

  • 如果你希望得到`Books`对象的`Books`集合*明显不完整*(因为它被虚构过滤),那么这并不是LINQ打算如何工作的.LINQ查询返回的每个`Author`对象旨在表示DB中的`Author`实体,而不是它的更改版本. (2认同)