包括Entity Framework TPH類的導航屬性

entity-framework inheritance navigation-properties

我有一個EF層次結構(顯著簡化)看起來像這樣:

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

換句話說,一個房間可以包含多個會話;每個Session可以包含多個Whiteboards;每個白板可以包含多個WhiteboardShapes。這些形狀可以是各種類型,包括WhiteboardShapePolyline,它本身可以包含多個PolylinePoints。

當遠程用戶最初連接到房間時,我需要將整個對像圖傳遞給該用戶,並且我試圖找出如何盡可能有效地將該圖從數據庫加載到內存中。

當然,現在,EF允許您進行急切加載,如下所示:

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

但Include()不允許我加載PolylinePoints。具體來說,如果我嘗試:

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

我得到異常“指定的包含路徑無效.EntityType'SlideLinc.Model.WhiteboardShape'不會聲明名為'PolylinePoint'的導航屬性。”

這也不起作用:

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

這也不是:

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

也沒有任何其他方式來構建我能想到的導航路徑。

我最終做到這一點的方式看起來像是對我的黑客攻擊:

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

它可以工作,但它的代碼比我想要的要多得多,並且它比我想要的更多數據庫訪問。

我找到的最接近的答案就在這裡 ,但我那可憐的Linq飢餓的大腦無法弄清楚如何將示例代碼轉換為我所擁有的更複雜的層次結構;此外,該鏈接的示例代碼很難看,難以理解。我真的不希望我的整個對象層次結構取決於EF內部如何構建其層次結構的模糊和不可見的副作用。

還有其他建議嗎?

一般承認的答案

我可能會使用投影。而不是返回實體類型,投影到輕量級數據傳輸對像或匿名類型。投影時(例如,使用LINQ查詢),加載會自動進行。在這種情況下,您無需指定Include。


熱門答案

我只是遇到了類似的問題(更簡單的導航路徑),我意識到Designer.cs文件中的PropertyName不是我所期望的。一旦我將它更改為Designer文件中的PropertyName,它一切正常 - 還要注意我做了兩個不同的路徑:

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


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因