Note that there are some explanatory texts on larger screens.

plurals
  1. POIncluding navigation properties from Entity Framework TPH classes
    primarykey
    data
    text
    <p>I've got an EF hierarchy that (dramatically simplified) looks something like this:</p> <pre><code>class Room { EntityCollection&lt;Session&gt; Sessions; } class Session { EntityCollection&lt;Whiteboard&gt; Whiteboards; EntityReference Room; } class Whiteboard { EntityCollection&lt;WhiteboardShape&gt; WhiteboardShapes; EntityReference Session; } abstract class WhiteboardShape { EntityReference Whiteboard; } class WhiteboardShapeEllipse : WhiteboardShape { } class WhiteboardShapePolyline { WhiteboardShape { EntityCollection&lt;PolylinePoint&gt; PolylinePoints } class PolylinePoint { EntityReference&lt;WhiteboardShapePolyline&gt; WhiteboardShapePolylineReference; } </code></pre> <p>In other words, a Room can contain multiple sessions; each Session can contain multiple Whiteboards; and each Whiteboard can contain multiple WhiteboardShapes. These shapes can be of various types, including a WhiteboardShapePolyline, which itself can contain multiple PolylinePoints.</p> <p>When a remote user initially connects to the room, I need to pass the entire object graph to that user, and I'm trying to figure out how to load that graph from the database into memory as efficiently as possible.</p> <p>Now, of course, the EF allows for you to do eager loading, like so:</p> <pre><code> Room room = ctx.Room .Include("Sessions.Whiteboards") .FirstOrDefault(r =&gt; r.OwnerID == ownerUserID &amp;&amp; r.Name == roomName); </code></pre> <p>But Include() doesn't let me load up the PolylinePoints. Specifically, if I try:</p> <pre><code> Room room = ctx.Room .Include("Sessions.Whiteboards.WhiteboardShape.PolylinePoint") .FirstOrDefault(r =&gt; r.OwnerID == ownerUserID &amp;&amp; r.Name == roomName); </code></pre> <p>I get the exception "A specified Include path is not valid. The EntityType 'SlideLinc.Model.WhiteboardShape' does not declare a navigation property with the name 'PolylinePoint'." </p> <p>Nor does this work: </p> <pre><code>.Include("Sessions.Whiteboards.WhiteboardShapePolyline.PolylinePoint") </code></pre> <p>Nor does this:</p> <pre><code>.Include("Sessions.Whiteboards.WhiteboardShape.WhiteboardShapePolyline.PolylinePoint") </code></pre> <p>Nor any other way of framing the navigation path that I can think of.</p> <p>The way that I've ended up doing it sure <i>seems</i> like a hack to me:</p> <pre><code> // 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(); } } } } } } </code></pre> <p>It works, but it's a lot more code than I want, and it's a whole bunch more database accesses than I want. </p> <p>The closest answer I've found is <a href="https://stackoverflow.com/questions/944332/entity-framework-inheritance-and-include">here</a>, but my poor Linq-starved brain can't figure out how to translate the example code into the more complicated hierarchy that I've got; plus, the sample code at that link is damned ugly and difficult to understand. I don't really want my entire object hierarchy depending on an obscure and invisible side-effect of how the EF internally constructs its hierarchies.</p> <p>Any other suggestions?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload