2010-08-23 16 views
17

Questo è per Entity Framework for .NET 3.5:Filter il "Include" tavolo su Entity Framework interrogazione

ho la necessità di interrogare un tavolo e includo una raccolta di "molti" tavola di un uno-a -molte relazioni. Sto cercando di filtrare quella raccolta come parte della query - Sono abbastanza nuovo per Entity Framework e ho difficoltà a capirlo.

Esempio semplificato: Autore ha Libri e Libro ha una colonna IsFiction. Voglio un elenco filtrato di autori, insieme a tutti i libri di narrativa.

senza il filtro, è facile:

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

posso filtrare dopo il fatto, qualcosa di simile:

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

Ma il problema è che la query originale già correva, e comprendeva questi risultati , che è l'elaborazione del database non necessaria.

posso interrogare separatamente, come:

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

Ma naturalmente questo è un invito a tutti gli autori, che voglio evitare pure.

posso andare a ritroso, come:

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

Ma poi sono tornato al problema originale, solo che adesso sul lato autore invece del lato libro.

Ci deve essere una soluzione che comprende tutto - posso farlo in SQL abbastanza facilmente:

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

Qualche suggerimento?

+3

Vota per filtrare Include [qui] (https://entityframework.codeplex.com/workitem/47)! – Chris

risposta

14

La strada da seguire:

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

Un altro modo, derivato dal SQL in fondo alla tua domanda:

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

La principale differenza tra questi due è che il primo sarà essenzialmente darà una raccolta di autori più la lista dei libri di narrativa per ciascun autore (che può essere vuota); mentre il secondo ti darà una collezione di coppie autore/libri (quindi non restituisce nessun autore senza libri di narrativa).

+0

Grazie per l'idea. Spero di ottenere effettivamente una raccolta di oggetti Autore, se possibile, non di oggetti anonimi digitati. Sulla stessa nota, se avessi preso quell'oggetto anonimo e inserito la raccolta Libri d'autore, non restituirebbe l'intera collezione di libri, non solo quelli di fiction? –

+0

@Joe Enos: Se hai elencato la raccolta 'Books' di' Author', sì, ovviamente. Ecco perché c'è la proprietà 'FictionBooks ':) – Timwi

+2

Se speri di ottenere oggetti' Autore' la cui raccolta 'Libri' è * esplicitamente incompleta * (perché è filtrata dalla fictionness), allora questo non è esattamente il modo in cui LINQ intende funzionare . Ogni oggetto 'Autore' restituito da una query LINQ è destinato a rappresentare l'entità' Author' nel DB, non una versione modificata di esso. – Timwi

Problemi correlati