2009-07-21 15 views
3

ich ein EF-Hierarchie haben, die (dramatisch vereinfacht) etwa wie folgt aussieht:Einschließlich Navigationseigenschaften von Entity Framework TPH Klassen

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 kann ein Raum mehrere Sitzungen enthalten; Jede Sitzung kann mehrere Whiteboards enthalten. und jedes Whiteboard kann mehrere Whiteboard-Formen enthalten. Diese Shapes können verschiedene Typen aufweisen, einschließlich einer WhiteboardShapePolyline, die wiederum mehrere PolylinePoints enthalten kann.

Wenn ein Remote-Benutzer sich anfänglich mit dem Raum verbindet, muss ich das gesamte Objektdiagramm an diesen Benutzer übergeben und ich versuche herauszufinden, wie dieses Diagramm von der Datenbank so effizient wie möglich in den Speicher geladen wird.

Nun, natürlich, ermöglicht es dem EF für Sie gerne Laden zu tun, etwa so:

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

Aber include() nicht mir die PolylinePoints laden nicht lassen. Insbesondere dann, wenn ich versuche:

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

ich die Exception „A angegebenen Include Pfad ungültig Die EntityType‚SlideLinc.Model.WhiteboardShape‘keine Navigationseigenschaft mit dem Namen‚PolylinePoint‘erklären..“

Nor funktionierts:

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

auch nicht dies:

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

noch irgendeine andere Art und Weise den Navigationspfad von Rahmen, die ich mir vorstellen kann.

Die Art und Weise, die ich am Ende habe es sicher tun scheint wie ein Hack zu mir:

 // 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 will, und es ist eine ganze Menge mehr Datenbankzugriffe, als ich möchte.

Die nächste Antwort, die ich gefunden habe, ist here, aber mein armes Linq-ausgehungertes Gehirn kann nicht herausfinden, wie man den Beispielcode in die kompliziertere Hierarchie übersetzt, die ich habe; Außerdem ist der Beispielcode in diesem Link verdammt hässlich und schwer zu verstehen. Ich möchte nicht wirklich, dass meine gesamte Objekthierarchie von einem obskuren und unsichtbaren Nebeneffekt abhängt, wie die EF ihre Hierarchien intern konstruiert.

Haben Sie noch weitere Vorschläge?

Antwort

3

Ich würde wahrscheinlich Projektion dafür verwenden. Anstatt Entitätstypen zurückzugeben, projizieren Sie auf einfache Datenübertragungsobjekte oder anonyme Typen. Wenn Sie (z. B. mit einer LINQ-Abfrage) projizieren, wird das Laden automatisch ausgeführt. Sie müssen in diesem Fall kein Include angeben.

0

Ich hatte gerade ein ähnliches Problem mit Ihrem (einfacher Navigationsweg) und ich erkannte, dass der PropertyName in der Designer.cs-Datei nicht das war, was ich erwartet hatte. Sobald ich es in der Designer-Datei in den PropertyName geändert hat, hat alles gut funktioniert - auch ich habe zwei verschiedene Pfade gemacht, die wurden:

.Include("UnexpectedNameA").Include("UnexpectedNameB") 
Verwandte Themen