EF LINQ incluye entidades múltiples y anidadas


Ok, tengo entidades de tres niveles con la siguiente jerarquía: Curso -> Módulo -> Capítulo

Aquí estaba la declaración original de EF LINQ:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Single(x => x.Id == id); 

Ahora, quiero incluir otra entidad llamada Lab que está asociada con un curso.

¿Cómo incluyo la entidad Lab?

Probé lo siguiente pero no funcionó:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters) && i.Lab)
                .Single(x => x.Id == id); 

¿Alguna idea sobre la inclusión de la 2ª Entidad?

Cualquier consejo o información sería muy apreciada. ¡Gracias!

Author: AnimaSola, 2013-04-02

5 answers

¿Has intentado añadir otro Include:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Include(i => i.Lab)
                .Single(x => x.Id == id);

Su solución falla porque Include no toma un operador booleano

Include(i => i.Modules.Select(s => s.Chapters) &&          i.Lab)
                           ^^^                  ^             ^ 
                          list           bool operator    other list

Actualización Para obtener más información, descargue LINQPad y mire las muestras. Creo que es la forma más rápida de familiarizarse con Linq y Lambda.

Como inicio - la diferencia entre Select y Include es que con un Select usted decide qué quieres volver (también conocido como proyección). El Incluir es un Carga Ansiosa función, que le dice a Entity Framework que desea que incluya datos de otras tablas.

La sintaxis Include también puede estar en cadena. Así:

           db.Courses
            .Include("Module.Chapter")
            .Include("Lab")
            .Single(x => x.Id == id);

Pero las muestras en LinqPad explica esto mejor.

 206
Author: Jens Kloster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-23 16:40:10

Include es una parte de fluent interface, por lo que puede escribir múltiples Include declaraciones cada uno después de otro

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 
 21
Author: Ilya Ivanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-02 12:55:59

También puedes probar

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
 16
Author: Martin Larsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-05 11:13:50

En Entity Framework Core (EF.core) puede usar .ThenInclude para incluir los siguientes niveles.

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

Más información: https://docs.microsoft.com/en-us/ef/core/querying/related-data

Nota: Digamos que necesita múltiples ThenInclude() en blog.Posts, simplemente repita el Include(blog => blog.Posts) y haga otro ThenInclude(post => post.Other).

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Other)
 .ToList();
 11
Author: Nick N.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-05 12:18:04

Uno puede escribir un método de extensión como este:

    /// <summary>
    /// Includes an array of navigation properties for the specified query 
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <param name="query">The query to include navigation properties for that</param>
    /// <param name="navProperties">The array of navigation properties to include</param>
    /// <returns></returns>
    public static IQueryable<T> Include<T>(this IQueryable<T> query, params string[] navProperties)
        where T : class
    {
        foreach (var navProperty in navProperties)
            query = query.Include(navProperty);

        return query;
    }

Y usarlo así incluso en una implementación genérica:

string[] includedNavigationProperties = new string[] { "NavProp1.SubNavProp", "NavProp2" };

var query = context.Set<T>()
.Include(includedNavigationProperties);
 1
Author: Mohsen Afshin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-08 07:43:01