从实体框架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。这些形状可以是各种类型的,包括一个WhiteboardShapePolyline,其本身可以包含多个PolylinePoints。
当一个远程用户最初连接到房间,我需要将整个对象图传递给用户,并且我试图找出如何尽可能有效地从数据库装载到内存中该曲线图。
现在,当然,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);
我得到的异常“A指定包含路径是无效的。在的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文件不是我的预期。有一次,我在设计文件中所有工作得很好改成了属性名 - 也注意到我做这成为两条不同的路径:
.Include("UnexpectedNameA").Include("UnexpectedNameB")