2009-09-22 25 views
8

Creo que hay un puesto similar aquí sobre esto, pero no es exactamente lo mismo ...Entity Framework - ¿Herencia con .Include?

tengo dos entidades en mi modelo de EF - llamémosles persona y desarrollador, con este último que hereda de la primera.

También tengo una asociación en Developer llamada Qualifications. Esto no es visible en la entidad Persona.

Si estoy escribiendo una consulta en relación con el contexto, ¿cómo puedo .Incluir() automáticamente las calificaciones del desarrollador, p.

de los empleados en context.Employee .include ("Títulos") de selección empleado

no funciona ... EF se queja de que no existe la relación (supongo que debido a que no existe en Empleado - pero no hay entidad Desarrolladora en el contexto, solo Empleado).

Respuesta

0

No estoy familiarizado con EF, pero esto me parece un problema de herencia estándar. Si desea acceder a las propiedades exclusivas de una clase hija de una colección de objetos "parentales" (donde los objetos reales pueden o no ser instancias de la clase hija), entonces necesita verificar el tipo de objeto y echarlo al niño donde sea apropiado, entonces puede acceder a las propiedades únicas.

¿Qué esperaría que volviera la declaración dada si algunos o todos los objetos no eran desarrolladores?

+0

Hola ... No debería intentar cargar en las entidades secundarias para la clase base, porque no existen. Hago el casting para verificar las propiedades del niño, etc., pero el objetivo de la inclusión es leerlo todo de una vez (tenga en cuenta que EF no admite la carga diferida). –

+0

Creo que me inclino a no subclasificar Persona sino crear otra clase llamada Desarrollador que tiene-una Persona, de esa manera usted probablemente pueda recuperar una colección de Persona y, a través de la asociación, pueda recuperar aquellas a las que hace referencia un Desarrollador y desde ese objeto desarrollador podrá encontrar aquellos con calificaciones. Realmente no estoy seguro de que sea posible hacer lo que intentas hacer usando la jerarquía de clases que has indicado. – Lazarus

2

¿Qué tal esto:

var results = from developer in ctx.Employee.OfType<Developer>() 
       select new {developer, Qualifications = developer.Qualifications}; 

Para cosas son interesantes aquí:

  1. estamos excluyendo los empleados que no son desarrolladores
  2. entonces proyectando sus requisitos y como un efecto secundario de esa proyección, algo llamado corrección con relleno cada desarrollador .Calificaciones también. Es decir. esta es otra forma de lograr el mismo efecto que Include().

si posteriormente hacer esto:

var developers = from anon in developers.AsEnumerable() 
       select anon.Developer; 

Usted recibirá sólo los desarrolladores, y tendrán sus calificaciones cargado también.

Ver Tip 1 para obtener más información sobre por qué esto funciona

Esperanza esto ayuda

Alex

+0

Hola, gracias por la sugerencia. ¡Lo probaré! Sin embargo, suena un poco como si esto no fuera una solución "respaldada oficialmente" desde el enlace que proporcionaste. Lo he solucionado temporalmente al llamar a Load en la colección secundaria, pero esto da como resultado una llamada SQL por separado, así que estoy dispuesto a evitarla si es posible. Gracias de nuevo. –

+1

Aunque una cosa me acabo de dar cuenta, el método en el que este código se encuentra debería ser capaz de trabajar tanto con clases derivadas como no derivadas, es decir, debería recuperar una colección de Empleados, de los cuales algunos pueden ser desarrolladores (que deberían tienen sus calificaciones completadas). –

+1

El bit que no se admite oficialmente en el enlace fue la clasificación de la colección. La carga real de la colección (todo lo que se usa arriba) es totalmente compatible. –

10

me he encontrado con este problema y experimentó un poco. Esto es lo que encontré funcionó con LINQ 2 Entity.

Digamos que tenemos en su ejemplo Persona < - Desarrollador ---- Calificaciones.

Si desea seleccionar un Desarrollador con las calificaciones incluidas, puede hacerlo.

var dev = (from d in context.Persons.OfType<Developer> 
          .Include("Qualifications") 
      where d.ID == id 
      select d).FirstOfDefault(); 

Ahora digamos que tenemos otra asociación entre la persona y dirección, también podemos incluir la dirección en la selección también usando LINQ 2 Entidad.

var dev = (from d in context.Persons 
          .Include("Address") 
          .OfType<Developer>() 
          .Include("Qualifications") 
      where d.ID == id 
      select d).FirstOfDefault(); 

Aviso cómo he incluido las cosas que tenía antes de mi conversión al tipo y también se incluye de nuevo después de la conversión. Ambos incluyen ahora deberían funcionar juntos sin ningún problema. He probado estos métodos y ambos funcionan. Espero que funcionen para usted dado que tiene su configuración de herencia correctamente.

GL.

2

Sobre la base de la respuesta de Tri Q, pero para los que prefieren el enfoque '.load()', puede utilizar:

context.Persons.OfType<Developer>().Include(t => t.Qualifications).Load(); 

lo uso en mi DbContext. Creé el método LoadDb(), que carga todos los datos que necesito. Entonces puedo usarlo en muchos proyectos.

Cuestiones relacionadas