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

つまり、Roomには複数のセッションを含めることができます。各セッションは複数のホワイトボードを含むことができます。各ホワイトボードには、複数のWhiteboardShapesを含めることができます。これらの形状は、それ自体が複数のPolylinePointを含むことができるWhiteboardShapePolylineを含む、さまざまな種類のものにすることができます。

リモートユーザーが最初に会議室に接続するときは、オブジェクトグラフ全体をそのユーザーに渡す必要があります。そのグラフをデータベースからメモリにできるだけ効率的にロードする方法を見つけようとしています。

さて、もちろん、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クエリで)投影するとき、ロードは自動的に起こります。この場合、インクルードを指定する必要はありません。


人気のある回答

私はあなたと似たような問題を抱えていました(より簡単なナビゲーションパス)。そしてDesigner.csファイルのPropertyNameが私の期待したものではないことに気づきました。 DesignerファイルでPropertyNameに変更すると、すべてうまくいきました - また、2つの異なるパスを行ったことにも注意してください。

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


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ