3

我有一个 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; }

换句话说,一个房间可以包含多个会话;每个会话可以包含多个白板;每个 Whiteboard 可以包含多个 WhiteboardShape。这些形状可以是各种类型,包括 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 如何在内部构建其层次结构的模糊和不可见的副作用。

还有其他建议吗?

4

2 回答 2

3

我可能会为此使用投影。不是返回实体类型,而是投射到轻量级数据传输对象或匿名类型上。当您进行项目时(例如,使用 LINQ 查询),加载会自动发生。在这种情况下,您不需要指定 Include。

于 2009-07-22T13:20:07.697 回答
0

I was just having a similar problem to yours (easier naviagation path) and I realised that the PropertyName in the Designer.cs file was not what I expected. Once I changed it to the PropertyName in the Designer file it all worked fine - also note I did two different paths which became:

.Include("UnexpectedNameA").Include("UnexpectedNameB")
于 2012-07-19T22:19:53.900 回答