2010-08-23 36 views
17

這是實體框架.NET 3.5:過濾器「包含」在實體表框架查詢

我需要查詢一個表,包括一對的「多」表的集合多種關係。我試圖將該集合作爲查詢的一部分進行過濾 - 我對Entity Framework非常陌生,但我很難搞清楚它。

簡化示例:作者有圖書,圖書有IsFiction列。我想要一個過濾的作者列表,以及所有的小說類書籍。

如果沒有過濾器,很容易:

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

我可以在事後進行過濾,像:

var fictionBooks = a.Books.Where(b => b.IsFiction); 

但問題是,原來的查詢已經運行,幷包含這些結果,這是不必要的數據庫處理。

我可以單獨查詢,如:

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; 
} 

當然,這是一個呼籲每一個作家,我想避免爲好,但。

我可以倒着走,如:

var allBooks = from b in db.Books.Include("Author") 
       where b.IsFiction 
       select b; 

但隨後我現在回到原來的問題,但在筆者側,而不是書的一面。

必須有涵蓋一切的解決方案 - 我能做到這一點的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 

有什麼建議?

+3

過濾投票包括[這裏](https://entityframework.codeplex.com/workitem/47)! – Chris 2013-09-27 07:31:46

回答

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) 
     }; 

的另一種方式,從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 }; 

這兩者之間的主要區別在於,第一個將基本放棄你是作者的集合加上每個作者的小說書目列表(可能是空的);而第二個會給你一個作者/書籍對的集合(所以它不會返回任何沒有小說書籍的作者)。

+0

感謝您的想法。如果可能的話,我希望實際獲得Author對象的集合,而不是匿名類型的對象。在同樣的筆記中,如果我確實採用了匿名類型的對象並枚舉了作者的書籍集合,那麼它是否不會返回整本書集,而不僅僅是小說集? – 2010-08-23 05:17:46

+0

@Joe Enos:當然,如果你列舉了作者的書籍集合。這就是爲什麼有'FictionBooks'屬性:) – Timwi 2010-08-23 05:20:38

+2

如果你希望得到'書籍'集合*顯式不完整*(因爲它被虛構過濾)的'作者'對象,那麼這不是真的如何工作。由LINQ查詢返回的每個'Author'對象都是爲了表示數據庫中的'Author'實體,而不是它的修改版本。 – Timwi 2010-08-23 05:24:30