2010-08-23 15 views
17

Esto es para Entity Framework de .NET 3.5:Filtrar la "Incluye" tabla de la Entidad consulta marco

tengo la necesidad de consultar una tabla e incluyen una colección de la tabla "varios" de un uno-a -Mucha relación. Intento filtrar esa colección como parte de la consulta: soy bastante nuevo en Entity Framework y tengo problemas para descubrirlo.

Ejemplo simplificado: el autor tiene Libros, y el Libro tiene una columna IsFiction. Quiero una lista filtrada de autores, junto con todos los libros de ficción.

Sin el filtro, es fácil:

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

que puede filtrar después del hecho, algo así como:

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

Pero el problema es que la consulta original ya se corrió, e incluyó los resultados , que es un procesamiento de base de datos innecesario.

que puede consultar por separado, como:

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

Pero por supuesto que es una llamada para cada autor, lo que quiero evitar así.

que puede ir hacia atrás, como:

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

Pero entonces estoy de vuelta al problema original, excepto que ahora en el lado de autor en lugar de la parte del libro.

Tiene que haber una solución que abarca todo - Puedo hacerlo en SQL con bastante facilidad:

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

¿Alguna sugerencia?

+3

Votar por filtrado Incluir [aquí] (https://entityframework.codeplex.com/workitem/47)! – Chris

Respuesta

14

El camino a seguir:

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

Otra forma, derivado del SQL en la parte inferior de su pregunta:

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 principal diferencia entre estos dos es que el primero de ellos, básicamente, dar usted una colección de autores más la lista de libros de ficción para cada autor (que puede estar vacía); mientras que el segundo le dará una colección de pares de autor/libros (para que no devuelva ningún autor sin libros de ficción).

+0

Gracias por la idea. Espero obtener una colección de objetos Autor si es posible, no objetos anónimos. En la misma nota, si tomé ese objeto anotado de forma anónima y enumeré la colección de libros del autor, ¿no devolvería toda la colección de libros, no solo los de ficción? –

+0

@Joe Enos: si enumeró la colección 'Books' de' Author', sí, por supuesto. Es por eso que existe la propiedad 'FictionBooks' :) – Timwi

+2

Si esperas obtener objetos' Autor' cuya colección 'Books' está * explícitamente incompleta * (porque está filtrada por ficción), entonces realmente no es así como LINQ debe funcionar . Cada objeto 'Autor' devuelto por una consulta LINQ tiene la intención de representar la entidad' Author' en el DB, no una versión alterada del mismo. – Timwi

Cuestiones relacionadas