Einschließlich Navigationseigenschaften aus Entity Framework-TPH-Klassen

entity-framework inheritance navigation-properties

Frage

Ich habe eine EF-Hierarchie, die (drastisch vereinfacht) in etwa wie folgt aussieht:

class Room { EntityCollection<Session> Sessions; }
class Session { EntityCollection<Whiteboard> Whiteboards; EntityReference Room; }
class Whiteboard { EntityCollection<WhiteboardShape> WhiteboardShapes; EntityReference Session; }
abstract class WhiteboardShape { EntityReference Whiteboard; }
class WhiteboardShapeEllipse : WhiteboardShape { }
class WhiteboardShapePolyline { WhiteboardShape { EntityCollection<PolylinePoint> PolylinePoints }
class PolylinePoint { EntityReference<WhiteboardShapePolyline> WhiteboardShapePolylineReference; }

Mit anderen Worten, ein Raum kann mehrere Sitzungen enthalten. Jede Session kann mehrere Whiteboards enthalten. und jedes Whiteboard kann mehrere WhiteboardShapes enthalten. Diese Shapes können verschiedenen Typen angehören, einschließlich WhiteboardShapePolyline, die selbst mehrere PolylinePoints enthalten kann.

Wenn ein Remote-Benutzer zunächst eine Verbindung mit dem Raum herstellt, muss ich das gesamte Objektdiagramm an diesen Benutzer übergeben, und ich versuche herauszufinden, wie das Diagramm aus der Datenbank so effizient wie möglich in den Speicher geladen werden kann.

Nun, natürlich, erlaubt Ihnen die EF ein eifriges Laden.

      Room room = ctx.Room
            .Include("Sessions.Whiteboards")
            .FirstOrDefault(r => r.OwnerID == ownerUserID && r.Name == roomName);

Bei Include () kann ich die PolylinePoints jedoch nicht laden. Insbesondere wenn ich versuche:

        Room room = ctx.Room
            .Include("Sessions.Whiteboards.WhiteboardShape.PolylinePoint")
            .FirstOrDefault(r => r.OwnerID == ownerUserID && r.Name == roomName);

Ich erhalte die Ausnahme "Ein angegebener Include-Pfad ist nicht gültig. Der EntityType 'SlideLinc.Model.WhiteboardShape' deklariert keine Navigationseigenschaft mit dem Namen 'PolylinePoint'."

Das funktioniert auch nicht:

.Include("Sessions.Whiteboards.WhiteboardShapePolyline.PolylinePoint")

Das tut es auch nicht:

.Include("Sessions.Whiteboards.WhiteboardShape.WhiteboardShapePolyline.PolylinePoint")

Noch eine andere Art, den Navigationspfad zu gestalten, den ich mir vorstellen kann.

Die Art und Weise, wie ich es am Ende gemacht habe, erscheint mir sicher wie ein Hack:

        // Make sure we've got everything loaded.
        if (room != null)
        {
            if (!room.Sessions.IsLoaded) { room.Sessions.Load(); }
            foreach (Session session in room.Sessions)
            {
                if (!session.Whiteboards.IsLoaded) { session.Whiteboards.Load(); }
                foreach (Whiteboard whiteboard in session.Whiteboards)
                {
                    if (!whiteboard.WhiteboardShape.IsLoaded) { whiteboard.WhiteboardShape.Load(); }
                    foreach (WhiteboardShape shape in whiteboard.WhiteboardShape)
                    {
                        if (shape is WhiteboardShapePolyline)
                        {
                            WhiteboardShapePolyline polyline = (WhiteboardShapePolyline)shape;
                            if (!polyline.PolylinePoints.IsLoaded) { polyline.PolylinePoints.Load(); }
                        }
                    }
                }
            }
        }

Es funktioniert, aber es ist viel mehr Code, als ich möchte, und es ist eine ganze Menge mehr Datenbankzugriffe, als ich möchte.

Die nächste Antwort, die ich gefunden habe, ist hier , aber mein armes Linq-hungerndes Gehirn kann nicht herausfinden, wie ich den Beispielcode in die kompliziertere Hierarchie übersetzen kann, die ich habe. Außerdem ist der Beispielcode unter diesem Link verdammt hässlich und schwer zu verstehen. Ich möchte nicht, dass meine gesamte Objekthierarchie von einem obskuren und unsichtbaren Nebeneffekt der internen Hierarchie der EF abhängig ist.

Irgendwelche anderen Vorschläge?

Akzeptierte Antwort

Ich würde wahrscheinlich Projektion dafür verwenden. Projizieren Sie nicht Entitätstypen zurück, sondern projizieren Sie Datenobjekte oder anonyme Typen. Wenn Sie projektieren (z. B. mit einer LINQ-Abfrage), erfolgt das Laden automatisch. In diesem Fall müssen Sie kein Include angeben.


Beliebte Antwort

Ich hatte gerade ein ähnliches Problem wie Sie (einfacherer Navigationspfad), und mir wurde klar, dass der PropertyName in der Datei Designer.cs nicht das war, was ich erwartet hatte. Sobald ich es in PropertyName in der Designer-Datei geändert habe, hat alles gut funktioniert - auch ich habe zwei verschiedene Pfade gemacht, die wurden:

.Include("UnexpectedNameA").Include("UnexpectedNameB")


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum