2011-06-24 14 views
8

Utilizo Entity Framework Code First y me encontré con un pequeño bloque de carreteras. Tengo una clase "Persona" se define como tal:Código de Entity Framework First IQueryable

public class Person 
{ 
    public Guid Id { get; set; } 
    public virtual ICollection<History> History { get; set; } 
} 

y un "historial" clase definida como tal:

public class History 
{ 
    public Guid Id { get; set; } 
    public virtual Person Owner { get; set; } 
    public DateTime OnDate { get; set; } 
} 

Sin embargo, cuando llamo:

IEnumerable<History> results = person.History 
           .OrderBy(h => h.OnDate) 
           .Take(50) 
           .ToArray(); 

Parece para extraer toda la historia de la persona, luego ordenarla y tal en la memoria. ¿Alguna recomendación sobre lo que me estoy perdiendo?

¡Gracias de antemano!

+0

¿Qué comportamiento esperabas ver? ¿No está logrando limitar el resultado a 50 registros? –

+3

Creo que el comportamiento esperado es pedirlo en la base de datos –

+1

Estaba esperando que envíe el pedido y limite al servidor, haciendo que el servidor SQL haga el pedido y la limitación. En su lugar, parece extraer todo el historial en la memoria, los más de 30,000 elementos para ese contacto y luego hacer el pedido y el límite en la memoria. – Terry

Respuesta

5

Porque está consultando un IEnumerable (es decir: LINQ to Objects) no IQueryable (es decir: LINQ to Entities) dado por EF.

lugar debe usar

IEnumerable<History> results = context.History.Where(h => h.Person.Id = "sfssd").OrderBy(h => h.OnDate).Take(50) 
+0

Este es el código EF primero - se supone que 'Persona' se recuperó de la base de datos, por lo tanto, su propiedad de navegación' Historial' está conectada al contexto. – BrokenGlass

+0

@BrokenGlass sí está conectado. Pero es del tipo 'ICollection ' not 'IQueryable '. De modo que cuando acceda a 'person.History' cargará todos los objetos del historial. – Eranga

+0

Ah, usted tiene razón, por supuesto, ya que la carga lenta entrará en acción y cargará la colección completa. Tengo mi +1 – BrokenGlass

0

Esta pregunta y la respuesta aceptada tanto son un poco viejo. Un código como este, como los puntos de la pregunta original, carga todo el historial de la persona en la base de datos, ¡no es bueno!

var results = person 
    .History 
    .OrderBy(h => h.OnDate) 
    .Take(50) 
    .ToArray(); 

Con EF 6 no es una solución fácil. Sin reorganizar su consulta, puede hacer que funcione de la manera IQueryable haciendo uso de DbContext.Entry method, DbEntryEntity.Collection method y DbCollectionEntry.Query method.

var results = dbContext 
    .Entry(person) 
    .Collection(p => p.History) 
    .Query() 
    .OrderBy(h => h.OnDate) 
    .Take(50) 
    .ToArray(); 
Cuestiones relacionadas