2011-06-07 16 views
14

tengo clases como:inmueble cargando Deseoso de clase derivada usando incluyen

Person 
{ 
    Name 
    Address 
} 

Employee : Person 
{ 
    Compensation - object 
} 

Visitor : Person 
{ 

} 

Si escribo LINQ:

var persons = Context.Persons 
       .Include("Compensation"); 

me sale error:

A specified Include path is not valid. The EntityType 'Person' does not declare a navigation property with the name 'Compensation'.

Funciona bien si Hago:

var persons = Context.Persons 
       .OfType<Employee>() 
       .Include("Compensation"); 

Pero me gustaría obtener empleados y visitantes en la misma consulta.

Parece que hay una solicitud de esta característica en EF4 UserVoice: http://data.uservoice.com/forums/72025-ado-net-entity-framework-ef-feature-suggestions/suggestions/1249289-include-property-of-derived-classes?ref=title

pero no parece que será hecho en el corto plazo.

¿Cuál es una buena solución para este problema?

Respuesta

7

Usted puede tratar de esta manera:

var persons = Context.Persons 
        .OfType<Employee>() 
        .Include("Compensation") 
        .Concat<Person>(Context.Persons.OfType<Visitor>()); 
+0

Cambio línea concat a: .Concat (Context.Persons.OfType ()); de lo contrario no compila. Cuando se ejecuta aún obtiene el mismo error que en la pregunta original. –

+0

@Ladislav, en mi caso, el tipo 'Person' no es abstracto, hay entidades que son' Person' ni 'Employee' ni' Visitor'. Tu ejemplo no me dará esos ** 'Person' ** s. Intentar combinar la consulta 'Persona' causa la excepción informada por el OP. Cualquier solución alternativa será realmente apreciada (en mi caso no es 'Persona', es' Transacción' sino lo que sea). – Shimmy

+0

@Shimmy: haga una pregunta por separado con un ejemplo del problema y haga referencia a esta. Los comentarios no son adecuados para resolver otro problema (incluso similar). –

0

Esta cosa horrible funciona:

var persons = context.Persons 
       .Concat(context.Employees 
        .Where(e => e.Compensation.Amount >= 0)) 
       .Concat(context.Visitors 
        .Where(v => v.SomeProperty == "AlwaysTrue")); 

No estoy seguro de por qué, pero cuando filtra en una propiedad de objeto, objeto de la propiedad es ansiosamente cargado. Si no desea filtrar esa propiedad, use una condición que siempre será cierta.

Descargo de responsabilidad: No tengo idea de qué tan eficiente es la consulta resultante. Comprobé el sql generado cuando probé esto en un escenario un poco más complicado y era muy grande.

+0

Esto es una locura ... Estoy intentando hacer que esto funcione, pero mi propiedad de navegación es una colección. Alguna idea sobre eso? Todo lo que he intentado todavía no carga la colección. – julealgon

2

Aquí es un buen ejemplo de cómo cargar Persons e incluyen Compensation para Employees

Reemplazar Reference() por Collection() para una propiedad de colección.

IQueryable<Person> GetPersons() 
{ 
    var persons = Context.Persons; 
    foreach(var entry in persons.OfType<Employee>()) 
     Context.Entry(entry).Reference(e => e.Compensation).Load(); 
    return persons; 
} 

No estoy seguro si es eficiente, pero funciona, y la intención es más clara que con las uniones.

Basándose en esta SO answer

2
var employees = context.Persons.OfType<Employee>().Include(x => x.Compensation).ToArray(); 

var nonEmployees = context.Persons.Except(context.Persons.OfType<Employee>()).ToArray(); 

var people = employees.Concat(nonEmployees);