EF LINQ include entità multiple e nidificate


155

Ok, ho entità a tre livelli con la seguente gerarchia: Corso -> Modulo -> Capitolo

Ecco la dichiarazione originale EF LINQ:

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

Ora, voglio includere un'altra entità chiamata Lab che è associata a un corso.

Come posso includere l'entità Lab?

Ho provato quanto segue ma non ha funzionato:

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

Qualche idea su come includere la 2a entità?

Qualsiasi consiglio o informazione sarebbe molto apprezzato. Grazie!


1
Aggiungerne un altro .Includedovrebbe funzionare a meno che tu non intenda dire che l'inclusione aggiuntiva è un nipote del Corso. Vedi questa o un'opzione migliore è questa
von v.

Related / possibile duplicato di stackoverflow.com/q/3356541
StuartLC

Risposte:


234

Hai provato ad aggiungere un altro Include:

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

La tua soluzione fallisce perché Includenon accetta un operatore booleano

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

Aggiornamento Per saperne di più, scarica LinqPad e guarda gli esempi. Penso che sia il modo più veloce per familiarizzare con Linq e Lambda.

Per iniziare, la differenza tra Selected Includeè quella con un Select decidi cosa vuoi restituire (aka proiezione). Includi è una funzione di caricamento desideroso , che dice a Entity Framework che vuoi che includa dati da altre tabelle.

La sintassi Includi può anche essere in stringa. Come questo:

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

Ma i campioni in LinqPad lo spiegano meglio.


Apprezzalo! Dove posso saperne di più? Sono particolarmente interessato alla differenza tra Includi e Seleziona
AnimaSola,

3
Solo questo ha funzionato per me: .Include("Module.Chapter"). Qualche idea sul perché sarebbe?
Jo Smo,

5
@JoSmo devi importare lo spazio dei nomi System.Data.Enityper accedere al metodo extension. maggiori informazioni qui
Jens Kloster,

using System.Data.Entity;fatto. Grazie!
Jo Smo,

1
votato per la menzione del brillante linqpad e suggerimento di usare System.Data.Entity, grazie Jens
Mike

38

In Entity Framework Core ( EF.core) è possibile utilizzare .ThenIncludeper includere i livelli successivi.

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

Ulteriori informazioni: https://docs.microsoft.com/en-us/ef/core/querying/related-data

Nota: Di che hai bisogno di più ThenInclude()su blog.Posts, basta ripetere la Include(blog => blog.Posts)e fare un altro 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();

In EF.core non riesco a fare .Include (i => i.Modules.Select (s => s.Chapters)), in particolare il .Select all'interno .Include. Qualcuno può confermare o parlare?
ttugates,

@ttugates Cosa intendi fare con questa selezione? Penso che quello che vuoi fare sia esattamente quello che fai con ThenIncludeEF core. Forse fai una domanda con un buon esempio, in modo che possiamo rispondere.
Nick N.

@Nick N - Query Linq Entity Framework: come su dove su più proprietà di navigazione e selezionare dalla terza proprietà di navigazione . Poiché ciò che seleziono non è quello su cui sto confrontando, le Include non sono necessarie, quindi la domanda è tangenziale. La mia domanda potrebbe essere troppo "ristretta" ma apprezzo qualsiasi aiuto.
ttugates,

1
Ah. In realtà, .ThenInclude () funziona. L'intellisense impiega un'eternità a visualizzare le relative tabelle.
Chris J,

23

Includefa parte di un'interfaccia fluida, quindi puoi scrivere più Includeistruzioni una dopo l'altra

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

apprezzalo! potresti indicarmi dove posso saperne di più? Grazie!
AnimaSola,

1
Sai qual è la sintassi se i moduli hanno più tabelle a cui vuoi unirti? Dici che si collega a Capitoli e qualcos'altro?
David Spence,

È fluente parte di .Net o è una libreria che deve essere installata?
codea,

19

Puoi anche provare

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);

4
Grazie - la notazione a punti nella stringa è molto utile
Evert

1
Questo può essere utile, ma un motivo per non usarlo è la facilità di refactoring in un secondo momento: se ad un certo punto rinominerai l'entità "Capitoli", l'altro esempio verrà automaticamente rinominato. Un altro è che gli errori verranno trovati prima: in fase di compilazione, non in fase di esecuzione.
MGOwen

2

Si può scrivere un metodo di estensione come questo:

    /// <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;
    }

E usalo così anche in un'implementazione generica:

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

var query = context.Set<T>()
.Include(includedNavigationProperties);

Stavo cercando la tua risposta, ma sta gettando eccezioni stackoverflow a causa di un ciclo infinito con se stesso.
Victoria S.

1
@VictoriaS., Puoi rinominare il metodo di estensione in modo che non interferisca con il realeInclude
Mohsen Afshin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.