实体框架 - 渴望加载子类相关对象

Gop*_*her 10 c# entity-framework-4

我想知道是否有可能为给定类的某些子类加载相关实体.

课程结构如下

Order与许多基本子类(SuborderBase)有关.MySubOrder类继承自SuborderBase.我想在加载Order时指定Include()加载MySubOrder相关实体(Customer)的路径,但是我得到一个错误,声称SuborderBase和Customer之间没有关系.但是MySubOrder和Customer之间存在关系.

以下是查询失败

Context.Orders.Include("SubOrderBases").Include("SubOrderBases.Customers")
Run Code Online (Sandbox Code Playgroud)

我该如何明确指定?

更新.实体计划如下 在此输入图像描述

Sla*_*uma 13

这是一个只需要一次往返的解决方案:

var orders = Context.Orders
    .Select(o => new
    {
        Order = o,
        SubOrderBases = o.SubOrderBases.Where(s => !(s is MyOrder)),
        MyOrdersWithCustomers = o.SubOrderBases.OfType<MyOrder>()
            .Select(m => new
            {
                MyOrder = m,
                Customers = m.Customers
            })
    })
    .ToList()  // <- query is executed here, the rest happens in memory
    .Select(a => 
    {
        a.Order.SubOrderBases = new List<SubOrderBase>(
            a.SubOrderBases.Concat(
            a.MyOrdersWithCustomers.Select(m => 
                {
                    m.MyOrder.Customers = m.Customers;
                    return m.MyOrder;
                })));
        return a.Order;
    })
    .ToList();
Run Code Online (Sandbox Code Playgroud)

它基本上是对匿名类型集合的投影.然后将查询结果转换为内存中的实体和导航属性.(它也适用于禁用跟踪.)

如果您不需要实体,则可以在第一个之后省略整个部分,ToList()并直接使用匿名对象中的结果.

如果你必须修改这个对象图,需要改变的跟踪,我不知道这种方法是安全的,因为数据被加载时,导航性能还没有完全设置-例如MyOrder.Customersnull在投射后,然后在内存中设置关系属性可能是检测到它不是一个修改,并在你打电话时造成麻烦SaveChanges.

针对只读方案进行预测,而不是进行修改.如果您需要更改跟踪,可能更安全的方法是在多个往返中加载完整实体,因为Include在您的情况下无法在单个往返中加载整个对象图.

  • 很好的答案,但这是一个非常愚蠢的必须做的事情.任何人都会认为EF团队忽视了关系数据库之间存在关系的事实. (9认同)