EF LINQ enthält mehrere und verschachtelte Entitäten

155

Ok, ich habe dreistufige Entitäten mit der folgenden Hierarchie: Kurs -> Modul -> Kapitel

Hier war die ursprüngliche EF LINQ-Anweisung:

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

Jetzt möchte ich eine weitere Entität namens Lab einfügen, die einem Kurs zugeordnet ist.

Wie füge ich die Lab-Entität hinzu?

Ich habe Folgendes versucht, aber es hat nicht funktioniert:

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

Irgendwelche Ideen zur Aufnahme der 2. Entität?

Jeder Ratschlag oder jede Information wäre sehr dankbar. Vielen Dank!

AnimaSola
quelle
1
Das Hinzufügen eines weiteren .Includesollte funktionieren, es sei denn, Sie meinen, dass das zusätzliche Include ein Enkelkind ist. Sehen Sie dies oder eine bessere Option ist dies
von v.
In Verbindung stehendes / mögliches Duplikat von stackoverflow.com/q/3356541
StuartLC

Antworten:

234

Haben Sie versucht, nur eine weitere hinzuzufügen Include:

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

Ihre Lösung schlägt fehl, da Includekein boolescher Operator erforderlich ist

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

Update Um mehr zu erfahren, laden Sie LinqPad herunter und sehen Sie sich die Beispiele an. Ich denke, es ist der schnellste Weg, sich mit Linq und Lambda vertraut zu machen.

Zunächst einmal - der Unterschied zwischen Selectund Includebesteht darin, dass Sie mit einem Select entscheiden, was Sie zurückgeben möchten (auch bekannt als Projektion). Das Include ist eine Funktion zum eifrigen Laden , die Entity Framework mitteilt, dass Daten aus anderen Tabellen enthalten sein sollen.

Die Include-Syntax kann auch eine Zeichenfolge sein. So was:

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

Die Beispiele in LinqPad erklären dies jedoch besser.

Jens Kloster
quelle
Bin dankbar! Wo kann ich mehr darüber erfahren? Ich interessiere mich besonders für den Unterschied zwischen Einschließen und Auswählen
AnimaSola
3
Nur dieser hat bei mir funktioniert : .Include("Module.Chapter"). Irgendeine Idee warum sollte das sein?
Jo Smo
5
@JoSmo Sie müssen den Namespace importieren, System.Data.Enityum auf die Erweiterungsmethode zuzugreifen. Weitere Infos hier
Jens Kloster
using System.Data.Entity;geschafft. Vielen Dank!
Jo Smo
1
Für die Erwähnung des brillanten Linqpads und den Tipp zur Verwendung von System.Data.Entity, thx Jens
Mike
38

In Entity Framework Core ( EF.core) können Sie die .ThenIncludenächsten Ebenen einbeziehen.

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

Weitere Informationen: https://docs.microsoft.com/en-us/ef/core/querying/related-data

Hinweis: Sagen Sie müssen Sie mehrere ThenInclude()auf blog.Posts, nur das wiederholen , Include(blog => blog.Posts)und das andere zu tun 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();
Nick N.
quelle
In EF.core bin ich anscheinend nicht in der Lage, .Include (i => i.Modules.Select (s => s.Chapters)) auszuführen, insbesondere die .Select inside .Include. Kann jemand bestätigen oder mit ihm sprechen?
ttugates
@ttugates Was beabsichtigen Sie mit dieser Auswahl zu tun? Ich denke, was Sie tun möchten, ist genau das, was Sie ThenIncludein EF Core tun . Stellen Sie vielleicht eine Frage mit einem guten Beispiel, damit wir sie beantworten können.
Nick N.
@Nick N - Linity- Abfrage für Entity Framework: So gehen Sie zu mehreren Nav-Eigenschaften und wählen Sie aus der 3. Nav-Eigenschaft aus . Da das, was ich auswähle, nicht das ist, worauf ich übereinstimme, sind die Includes nicht erforderlich, sodass die Frage tangential ist. Meine Frage mag zu "eng" sein, aber ich schätze jede Hilfe.
ttugates
1
Ah. Tatsächlich funktioniert .ThenInclude (). Es dauert nur ewig, bis der Intellisense die zugehörigen Tabellen anzeigt.
Chris J
23

Includeist Teil einer fließenden Benutzeroberfläche, sodass Sie mehrere IncludeAnweisungen nacheinander schreiben können

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 
Ilya Ivanov
quelle
bin dankbar! Können Sie mir zeigen, wo ich mehr darüber erfahren kann? Vielen Dank!
AnimaSola
1
Wissen Sie, wie die Syntax lautet, wenn Module mehrere Tabellen haben, denen Sie beitreten möchten? Sagen wir, es verlinkt auf Kapitel und etwas anderes?
David Spence
Ist fließend Teil von .Net oder ist dies eine Bibliothek, die installiert werden muss?
Codea
19

Sie können es auch versuchen

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
Martin Larsson
quelle
4
Vielen Dank - die Punktnotation in der Zeichenfolge sehr nützlich
Evert
1
Dies kann nützlich sein, aber ein Grund, dies nicht zu verwenden, ist die einfache spätere Umgestaltung: Wenn Sie die Entität "Kapitel" irgendwann umbenennen, wird das andere Beispiel automatisch umbenannt. Zum anderen werden Fehler früher gefunden: zur Kompilierungszeit, nicht zur Laufzeit.
MGOwen
2

Man kann eine Erweiterungsmethode wie folgt schreiben:

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

Und verwenden Sie es auch in einer generischen Implementierung so:

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

var query = context.Set<T>()
.Include(includedNavigationProperties);
Mohsen Afshin
quelle
Ich habe Ihre Antwort versucht, aber es werden aufgrund einer Endlosschleife mit sich selbst Stapelüberlauf-Ausnahmen ausgelöst.
Victoria S.
1
@ VictoriaS., Sie können die Erweiterungsmethode umbenennen, so dass es nicht mit dem realenInclude
Mohsen Afshin