Entity FrameworkのTPHクラスからナビゲーションプロパティを含みます
-
18-09-2019 - |
質問
私は(劇的に単純化された)次のようになります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; }
言い換えれば、ルームは、複数のセッションを含めることができます。各セッションには、複数のホワイトボードを含めることができます。各ホワイトボードは、複数のWhiteboardShapesを含めることができます。これらの形状は、それ自体が複数PolylinePointsを含むことができWhiteboardShapePolyline、を含む、様々な種類のものとすることができる。
リモートユーザーが最初に部屋に接続すると、、私はそのユーザーにオブジェクトグラフ全体を渡す必要がある、と私は可能な限り効率的にメモリにデータベースからそのグラフをロードする方法を把握しようとしています。
さて、もちろん、EFは、あなたが、熱心なロードを行うことが可能になりますので、同様ます:
Room room = ctx.Room
.Include("Sessions.Whiteboards")
.FirstOrDefault(r => r.OwnerID == ownerUserID && r.Name == roomName);
しかし、私は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クエリを持つ)を投影した場合、ロードは自動的に行われます。あなたは、この場合に含める指定する必要はありません。
他のヒント
私はあなた(簡単にnaviagationパス)と同様の問題を抱えていたと私はDesigner.csファイル内PropertyNameは、私が期待したものではないことに気づきました。 - 私はそれがすべてうまく働いたデザイナーファイル内のPropertyNameにそれを変更した後も、私はなった2つの異なるパスをした注意します:
.Include("UnexpectedNameA").Include("UnexpectedNameB")