从实体框架TPH类,包括导航性能(Including navigation properties f

2019-07-30 14:25发布

我有一个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在内部构造的层次结构的模糊和不可见的副作用。

任何其他的建议?

Answer 1:

我可能会使用投影此。 而不是返回实体类型,项目拖到轻量级数据传输对象或匿名类型。 当你的项目(例如,使用LINQ查询),装载自动发生。 你并不需要指定在这种情况下,一个包含。



Answer 2:

我只是有类似的问题给你(更容易naviagation路径),我意识到,在Designer.cs文件的属性名不是我的预期。 有一次,我在设计文件中所有工作得很好改成了属性名 - 也注意到我做这成为两个不同的路径:

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


文章来源: Including navigation properties from Entity Framework TPH classes