visual Entity Framework lädt untergeordnete Sammlung mit Sortierreihenfolge




poco generator c# (2)

Sie können es nicht direkt erreichen, da weder das Eager- noch das Lazy-Laden in EF das Ordnen oder Filtern unterstützt.

Ihre Optionen sind:

  • Sortieren Sie Daten in Ihrer Anwendung, nachdem Sie sie aus der Datenbank geladen haben
  • Führen Sie eine separate Abfrage aus, um untergeordnete Datensätze zu laden. Sobald Sie eine separate Abfrage verwenden, können Sie OrderBy

Die zweite Option kann beim expliziten Laden verwendet werden:

var parent = context.Parents.First(...);
var entry = context.Entry(parent);
entry.Collection(e => e.Children)
     .Query()
     .OrderBy(c => c.SortOrder)
     .Load();

Ich habe zwei Tische einen Eltern- und einen Kindertisch. Die untergeordnete Tabelle hat eine Spaltensortierung (ein numerischer Wert). Wegen der fehlenden Unterstützung der EF, um eine IListe inklusive der Sortierreihenfolge zu erhalten, ohne die Sortierreihenfolge zu offenbaren (siehe: Sortierreihenfolge der Sortierreihenfolge Entity Framework ), hat meine Kindklasse auch eine Eigenschaft SortOrder, so dass ich die Kinder mit der Sortierung speichern kann Auftrag.

Im Gegensatz zum Autor der referenzierten Frage versuche ich die Kinder immer sortiert zu laden. Wenn ich also eine Elterninstanz lade, erwarte ich, dass die Kindkollektion nach Sortierreihenfolge sortiert wird. Wie kann ich dieses Verhalten mit der Code First Fluent API und den POCO's erreichen?

Hinweis: Es ist keine Option, .Sort (...) für die Child-Sammlung aufzurufen.


Sie können dies effizient in einer einzigen Abfrage tun, die Grammatik ist nur peinlich:

var groups = await db.Parents
    .Where(p => p.Id == id)
    .Select(p => new
        {
            P = p,
            C = p.Children.OrderBy(c => c.SortIndex)
        })
    .ToArrayAsync();

// Query/db interaction is over, now grab what we wanted from what was fetched

var model = groups
    .Select(g => g.P)
    .FirstOrDefault();

Erläuterung

asynchrone Notiz

Ich habe zufällig die async Erweiterungen hier verwendet, die Sie wahrscheinlich verwenden sollten, aber Sie können die Funktion " await / async loswerden, wenn Sie eine synchrone Abfrage benötigen, ohne die effiziente Kindsortierung zu beeinträchtigen.

Erster Brocken

Standardmäßig werden alle aus dem DB abgerufenen EF-Objekte "verfolgt". Darüber hinaus ist die Entsprechung von EF zu SQL Select um anonyme Objekte herum angelegt, die Sie oben auswählen. Wenn das anonyme Objekt erstellt wird, werden die Objekte, die P und C zugewiesen sind, beide verfolgt, dh ihre Beziehungen werden notiert und ihr Status wird vom EF Change Tracker verwaltet. Da C eine Liste von untergeordneten P in P , obwohl Sie sie nicht ausdrücklich in Ihrem anonymen Objekt angefordert haben, lädt EF sie als diese untergeordnete Auflistung, da die Beziehung im Schema angezeigt wird.

Um mehr zu erfahren, können Sie das oben genannte in zwei separate Abfragen aufteilen, indem Sie nur das übergeordnete Objekt und dann nur die untergeordnete Liste in ganz anderen DB-Aufrufen laden. Der EF Change Tracker bemerkt und lädt die untergeordneten Elemente in das übergeordnete Objekt für Sie.

Zweites Stück

Wir haben EF dazu gebracht, die bestellten Kinder zurückzugeben. Jetzt greifen wir nur das Parent-Objekt - seine Kinder werden immer noch in der Reihenfolge angehängt, wie wir es wollten.

Nullen und Tabellen als Mengen

Es gibt einen peinlichen 2-Schritt hier hauptsächlich für Best Practices rund um Nullen; es ist da, um 2 Dinge zu tun:

  • Denken Sie an Dinge in der DB als Sätze bis zum absolut letzten Moment möglich.

  • Vermeiden Sie Null-Ausnahmen.

Mit anderen Worten, der letzte Brocken könnte sein:

var model = groups.First().P;

Wenn das Objekt jedoch nicht in der Datenbank vorhanden ist, wird es mit einer Null-Referenzausnahme ausgelöst. C # 6 führt jedoch eine andere Alternative ein, nämlich den Koaleszenzoperator für Null-Eigenschaften - so könnten Sie in Zukunft den letzten Teil ersetzen durch:

var model = groups.FirstOrDefault()?.P;




code-first