entity-framework - 包括 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可以包含多个Session;每个Session可以包含多个白板;每个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(); }
                        }
                    }
                }
            }
        }

它可以工作,但是代码比我想要的多得多,而且数据库访问也比我想要的多得多。

我找到的最接近的答案是 here ,但是我可怜的 Linq 饥饿大脑无法弄清楚如何将示例代码转换为我拥有的更复杂的层次结构;另外,该链接的示例代码非常丑陋且难以理解。我真的不希望我的整个对象层次结构依赖于 EF 如何内部构建其层次结构的模糊且不可见的副作用。

还有其他建议吗?

最佳答案

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

关于entity-framework - 包括 Entity Framework TPH 类的导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1162313/

相关文章:

entity-framework - Symfony 2.3 使用选择或其他类型将自定义数据传递给实体表单

c++ - 自动将一个对象添加到该对象父对象的 vector 中

c++ - 从用作数据部分的字符串派生的类

c# - 导航属性和级联删除

c# - Entity Framework 中对象属性中的 NULL 值

c# - 将应用程序 Web 部署到单独的 Web 服务器后出现 SQL Server 错误

entity-framework - 取消删除标记为 EntityState.Delete 的实体?

c# - 插入 Entity Framework 后导航属性为 NULL

c# - 如何与 Entity Framework 建立一对一或零的关系并公开子实体上的外键?

c++ - { token 之前的预期类名 - 非常简单