2010-08-23 11 views
17

To jest dla Entity Framework dla .NET 3.5:Przesączyć „obejmuje” tabeli na jednostkę zapytania Framework

mam potrzebę kwerendy w tabeli i zawierać zbiór „wiele” tabeli jeden-do - wiele związków. Próbuję filtrować tę kolekcję jako część kwerendy - Jestem całkiem nowy w Entity Framework i mam problem z jej odgadnięciem.

Uproszczony przykład: autor ma książki, a książka ma kolumnę IsFiction. Chcę mieć przefiltrowaną listę autorów wraz ze wszystkimi książkami fikcyjnymi.

bez filtra, to proste:

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

mogę filtrować po fakcie, coś jak:

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

Ale problemem jest to, że pierwotne zapytanie już zabrakło i objęły te wyniki , co jest niepotrzebnym przetwarzaniem bazy danych.

mogę zapytać osobno, jak:

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

Ale oczywiście to jest jeden wezwanie dla każdego autora, który chcę uniknąć, jak również.

mogę iść do tyłu, jak:

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

Ale jestem z powrotem do pierwotnego problemu, chyba teraz po stronie autora, a nie od strony księgowej.

Musi być rozwiązanie, które obejmuje wszystko - można to zrobić w SQL dość łatwo:

select * from author a 
left join book b on a.id = b.author_id and b.is_fiction = 1 
where a.birth_year > 1900 

Wszelkie sugestie?

+3

Głosuj na filtrowanie Dołącz [tutaj] (https://entityframework.codeplex.com/workitem/47)! – Chris

Odpowiedz

14

Droga naprzód:

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

Innym sposobem, pochodzące z SQL na dole zapytanie:

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

Główną różnicą między tymi dwoma jest to, że pierwszy z nich będzie po prostu dać ty zbiór autorów plus lista książek fikcyjnych dla każdego autora (które mogą być puste); natomiast drugi da ci kolekcję par autor/książka (więc nie zwraca żadnych autorów bez książek fikcyjnych).

+0

Dzięki za pomysł. Mam nadzieję, że w miarę możliwości dostanę kolekcję obiektów autorskich, a nie anonimowe obiekty wpisane na maszynie. Na tej samej zasadzie, gdybym wziął ten anonimowo napisany obiekt i wyliczył kolekcję książek autora, czy nie zwróciłby całej kolekcji książek, a nie tylko tych fikcyjnych? –

+0

@Joe Enos: Jeśli wymieniłeś kolekcję 'Books', tak, oczywiście. Dlatego istnieje własność 'FictionBooks' :) – Timwi

+2

Jeśli masz nadzieję uzyskać obiekty' Author', których kolekcja 'Books' jest wyraźnie niekompletna * (ponieważ jest filtrowana przez fikcję), to tak naprawdę nie jest to zamierzone działanie LINQ . Każdy obiekt 'Autor' zwrócony przez kwerendę LINQ ma reprezentować jednostkę' Author' w DB, a nie zmienioną jej wersję. – Timwi

Powiązane problemy