2012-05-30 45 views
221

El método Include() funciona bastante bien para las listas en los objetos. Pero, ¿y si necesito ir a dos niveles de profundidad? Por ejemplo, el siguiente método devolverá ApplicationServers con las propiedades incluidas que se muestran aquí. Sin embargo, ApplicationsWithOverrideGroup es otro contenedor que contiene otros objetos complejos. ¿Puedo hacer un Include() en esa propiedad también? ¿O cómo puedo conseguir que esa propiedad se cargue por completo?Entity Framework - Include Multiple Levels of Properties

Tal como está ahora, este método:

public IEnumerable<ApplicationServer> GetAll() 
{ 
    return this.Database.ApplicationServers 
     .Include(x => x.ApplicationsWithOverrideGroup)     
     .Include(x => x.ApplicationWithGroupToForceInstallList) 
     .Include(x => x.CustomVariableGroups)     
     .ToList(); 
} 

rellenará solamente la propiedad Enabled (abajo) y no la aplicación o propiedades CustomVariableGroup (abajo). ¿Cómo hago que esto suceda?

public class ApplicationWithOverrideVariableGroup : EntityBase 
{ 
    public bool Enabled { get; set; } 
    public Application Application { get; set; } 
    public CustomVariableGroup CustomVariableGroup { get; set; } 
} 
+0

Hola, ¿Por qué obtengo una excepción 'La expresión debe ser una expresión miembro' cuando intento esto: Para incluir una colección y luego una colección de un nivel hacia abajo:' query.Include (e => e.Level1Collection.Select (l1 => l1.Level2Collection)) '. –

+1

@BobHorn, tengo el mismo problema ... En mi caso, la anidación va en el fondo de varias capas, logré hacer una inclusión que usted señaló. En el SQL que se generó, pude ver que todas las columnas están regresando con un nombre de alias diferente como c1, c2 algo así. Mi pregunta es, ¿cómo puedo formar una colección DTO anidada de todos mis incluye :(.. Puede ser que usted puede tomar el ejemplo anterior, en el que estamos devolviendo todas las columnas sin ningún DTO personalizado (que a su vez es una colección de DTO) – TechQuery

Respuesta

418

Para EF 6

using System.Data.Entity; 

query.Include(x => x.Collection.Select(y => y.Property)) 

Ver Remarks para más ejemplos.

Asegúrese de agregar using System.Data.Entity; para obtener la versión de Include que admite una lambda.


Si está utilizando EF Core puede utilizar el nuevo método ThenInclude

query.Include(x => x.Collection) 
    .ThenInclude(x => x.Property); 
+1

No puedo hacer Include() en ApplicationsWithOverrideGroup. No aparece en intellisense. –

+0

No puedo usar su edición porque ApplicationsWithOverrideGroup es una lista. La aplicación es una propiedad de cada elemento de la lista, no de la propia lista. –

+1

Ahhhh, pero ese enlace que proporcionó parece proporcionar la respuesta. Permítanme intentar esto: incluir una colección y luego una colección de un nivel hacia abajo: query.Include (e => e.Level1Collection.Select (l1 => l1.Level2Collection)). –

43

Si te entiendo correctamente, estás preguntando por incluir propiedades anidadas. Si es así:

.Include(x => x.ApplicationsWithOverrideGroup.NestedProp) 

o

.Include("ApplicationsWithOverrideGroup.NestedProp") 

o

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}") 
+4

Gracias, puedo intentarlo. Esperaba poder mantener las cosas fuertemente tipadas y evitar literales de cadenas. Pero si así es como tiene que hacerse ... –

+0

Estuviste cerca. Puede que no haya sido claro que ApplicationsWithOverrideGroup era una lista. ¡Gracias por ayudar! –

+0

@Judo, tengo el mismo problema ... En mi caso, el anidamiento va muy abajo en varias capas, logré hacer una inclusión que usted señaló. En el SQL que se generó, pude ver todas las columnas están regresando con un nombre de alias diferente como c1, c2 algo así. Mi pregunta es, ¿cómo puedo formar una colección de DTO anidada de todas mis incluye :(.. Puede ser que pueda tomar el ejemplo anterior, en ese estamos devolviendo todas las columnas w sin ningún DTO personalizado (que en sí mismo es una colección de DTO) – TechQuery

24

El uso de "ThenInclude" para cargar mutiple niveles: Por ejemplo:

var blogs = context.Blogs 
    .Include(blog => blog.Posts) 
     .ThenInclude(post => post.Author) 
     .ThenInclude(author => author.Photo) 
    .ToList(); 
+36

Parece que esto es EF Core solamente –

+6

FYI: VS2017 el intellisense no funcionó para .ThenInclude. Solo escríbalo en cómo crees que debería ser y el resaltado de errores debería desaparecer. – JohnWrensby

+0

Quiero enfatizar el comentario de @JohnWrensby, el Intellisense a veces puede llevar mucho tiempo manejar estos ThenInclude, esto puede ser bastante confuso para los usuarios nuevos. También tuve casos en los que la expresión simple Incluir lambda no se manejaba correctamente, hasta que simplemente la escribes y compilas, ignorando los "errores" que se muestran en VS. – Pac0

13

hice una pequeño ayudante para Entity Framework 6 (estilo .Net Core), para incluir subentidades de una manera agradable.

Es en NuGet ahora: Instalar Paquete ThenInclude.EF6

using System.Data.Entity; 

var thenInclude = context.One.Include(x => x.Twoes) 
    .ThenInclude(x=> x.Threes) 
    .ThenInclude(x=> x.Fours) 
    .ThenInclude(x=> x.Fives) 
    .ThenInclude(x => x.Sixes) 
    .Include(x=> x.Other) 
    .ToList(); 
8

También tuve que usar múltiples incluye y al 3er nivel que tenía varias propiedades

(from e in context.JobCategorySet 
         where e.Id == id && 
          e.AgencyId == agencyId 
         select e) 
         .Include(x => x.JobCategorySkillDetails) 
         .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.DurationType)) 
         .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RuleType)) 
         .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RateType)) 
         .FirstOrDefaultAsync(); 

Esto puede ayudar a alguien:)

+0

se puede hacer esto sin repetir '.Include (x => x.Shifts.Select (r => r.Rate) .Select (rt => rt ......' – Multinerd

+0

bien depende, qué tan profundo quieres Vaya al – dnxit

3

Más EFCore examples on MSDN muestran que puede hacer algunas cosas bastante complejas con Include y ThenInclude.

Este es un buen ejemplo de lo complejo que puede obtener (todo esto es una declaración!):

viewModel.Instructors = await _context.Instructors 

     .Include(i => i.OfficeAssignment) 

     .Include(i => i.CourseAssignments) 
     .ThenInclude(i => i.Course) 
      .ThenInclude(i => i.Enrollments) 
       .ThenInclude(i => i.Student) 

     .Include(i => i.CourseAssignments) 
     .ThenInclude(i => i.Course) 
      .ThenInclude(i => i.Department) 

     .AsNoTracking() 
     .OrderBy(i => i.LastName) 
     .ToListAsync(); 

ver cómo se puede cadena Include incluso después ThenInclude y que tipo de 'resetea' de vuelta al nivel de la entidad de nivel superior (instructores).

Incluso puede repetir la misma colección de 'primer nivel' (CourseAssignments) varias veces seguidas de comandos ThenIncludes para obtener diferentes entidades secundarias.

Tenga en cuenta que su consulta real debe etiquetarse al final de la cadena Include o ThenIncludes. El siguiente no funciona:

Se recomienda encarecidamente que configure la tala y asegurarse de que sus consultas no están fuera de control si está incluyendo más de una o dos cosas. Es importante ver cómo funciona realmente, y notará que cada 'inclusión' por separado suele ser una nueva consulta para evitar uniones masivas y devolver datos redundantes.

AsNoTracking puede acelerar mucho las cosas si no tiene la intención de editar realmente las entidades y volver a guardarlas.

+0

¿Hay alguna forma de obtener tanto la Inscripción como los Departamentos sin su repetición? ¿Incluye el curso y curso? (Hasta ahora, parece que el Api puede ir más profundo con .ThenInclude, o volver al nivel superior con .Incluir, pero no hay nada que se quede en el mismo nivel?) –

+0

Si quieres cargar lazy, estad atentos a EF Core 2.1 https://blogs.msdn.microsoft.com/dotnet/2018/02/02/entity-framework-core -2-1-roadmap/pero si solo quieres cargar más en el mismo nivel, creo que esto es por diseño. No estoy seguro de lo que estás pensando, no requiere mucho más para hacer esto y es muy útil. reduce lo que vuelve de la base de datos. Una entidad puede tener solo uno o dos elementos del mismo nivel, pero también puede tener 50 para un proyecto grande, ser El hecho de hacer explícitas hace que tu aplicación sea mucho más rápida. –

Cuestiones relacionadas