2011-10-03 12 views
10

Me pregunto si existe la posibilidad de entidades relacionadas con la carga ansiosa para cierta subclase de clase dada.Marco de la entidad - Carga ansiosa de objetos relacionados con las subclases

estructura Class está por debajo de

Orden tiene relación con muchas clases suborden de base (SuborderBase). La clase MySubOrder hereda de SuborderBase. Deseo especificar la ruta de Include() para cargar las entidades relacionadas con MySubOrder (Customer) al cargar Order, pero recibí un error al afirmar que no existe relación entre SuborderBase y Customer. Pero la relación existe entre MySubOrder y Customer.

A continuación se consulta que falla

Context.Orders.Include("SubOrderBases").Include("SubOrderBases.Customers") 

¿Cómo puedo especificar que de manera explícita?

Actualización. esquema de entidad está por debajo enter image description here

+1

Probablemente no hay solución con carga ansiosa. A continuación, se incluye una solución con una proyección (solo funciona el tercer fragmento de código en la respuesta aceptada, no el segundo fragmento, vea comentarios en la respuesta): http://stackoverflow.com/questions/6586574/bottleneck-using-entity-framework- herencia. Aquí (http://stackoverflow.com/questions/7203303/how-do-i-deeply-eager-load-an-entity-with-a-reference-to-an-instance-of-a-persist) era un pregunta similar sin respuesta. – Slauma

+0

¿Puede bosquejar las clases y relaciones brevemente en el código ('Order',' SubOrderBase', 'MySubOrder',' Customer')? Al mirar las respuestas, las personas parecen malinterpretar su pregunta. También estoy inseguro ahora después de las primeras respuestas y comentarios. – Slauma

+0

Imagen añadida con el diagrama de clase – Gopher

Respuesta

13

Esta es una solución que requiere sólo un único ida y vuelta:

var orders = Context.Orders 
    .Select(o => new 
    { 
     Order = o, 
     SubOrderBases = o.SubOrderBases.Where(s => !(s is MyOrder)), 
     MyOrdersWithCustomers = o.SubOrderBases.OfType<MyOrder>() 
      .Select(m => new 
      { 
       MyOrder = m, 
       Customers = m.Customers 
      }) 
    }) 
    .ToList() // <- query is executed here, the rest happens in memory 
    .Select(a => 
    { 
     a.Order.SubOrderBases = new List<SubOrderBase>(
      a.SubOrderBases.Concat(
      a.MyOrdersWithCustomers.Select(m => 
       { 
        m.MyOrder.Customers = m.Customers; 
        return m.MyOrder; 
       }))); 
     return a.Order; 
    }) 
    .ToList(); 

Básicamente es una proyección en una colección de tipo anónimo. Luego, el resultado de la consulta se transforma en entidades y propiedades de navegación en la memoria. (También funciona con seguimiento deshabilitado).

Si no necesita entidades, puede omitir toda la parte después del primer ToList() y trabajar directamente con el resultado en los objetos anónimos.

Si debe modificar este gráfico de objetos y la necesidad de seguimiento de cambios, no estoy seguro de si este enfoque es seguro debido a las propiedades de navegación no se establecen por completo cuando se cargan los datos - por ejemplo MyOrder.Customers es null después de la proyección, y luego poner las propiedades de relación en la memoria podrían detectarse como una modificación que no es así y causar problemas al llamar al SaveChanges.

Las proyecciones están hechas para escenarios de solo lectura, no para modificaciones. Si necesita un seguimiento de cambios, la forma probablemente más segura es cargar entidades completas en múltiples recorridos de ida y vuelta ya que no hay forma de usar Include en una sola ida y vuelta para cargar todo el gráfico de objetos en su situación.

+0

¡Gracias! solución muy interesante!No es exactamente lo que quería, pero creo que este ejemplo será una gran inspiración – Gopher

+9

Gran respuesta, pero qué manera extraordinariamente tonta de tener que hacer cosas. Cualquiera pensaría que el equipo de EF pasó por alto el hecho de que las bases de datos relacionales tienen relaciones entre tablas. –

0

Supongamos u cargado la lista de pedidos como lstOrders, intente esto:

foreach (Orders order in lstOrders) 
    order.SubOrderBases.Load(); 

y lo mismo para los clientes ..

+2

sí, pero estoy pensando en cómo hacerlo con 1 consulta sql ... – Gopher

+2

intente esto: Context.Orders.Include ("SubOrderBases"). Include ("Customers") – Boomer

Cuestiones relacionadas