实体框架 - 加载子类相关对象 [英] Entity Framework - Eager loading of subclass related objects

查看:100
本文介绍了实体框架 - 加载子类相关对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有给予类某些子类加载相关实体的可能性。



类结构在



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



以下是查询失败

  Context.Orders.Include SubOrderBases)。Include(SubOrderBases.Customers)

如何明确指定? / p>

更新。实体方案低于

解决方案

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

  var orders = Context.Orders 
.Select(o => new
{
Order = o,
SubOrderBases = o.SubOrderBases.Where(s =>!(s是MyOrder )),
MyOrdersWithCustomers = o.SubOrderBases.OfType< MyOrder>()
.Select(m => new
{
MyOrder = m,
Customers = m.Customers
})
})
.ToList()//< - 在这里执行查询,其余发生在内存
.Select(a =>
{
a.Order.SubOrderBases = new List< SubOrderBase>(
a.SubOrderBases.Concat(
a.MyOrdersWithCustomers.Select(m =>
{
m.MyOrde客户=
return m.MyOrder;
})));
返回a.Order;
})
.ToList();

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



如果不需要实体,可以在第一个 ToList()并直接与匿名对象中的结果一起工作。



如果您必须修改此对象图并需要更改跟踪,我不知道这是否方法是安全的,因为导入属性在加载数据时没有完全设置 - 例如 MyOrder.Customers null 在调用 SaveChanges 后,投影后,然后设置内存中的关系属性可以被检测为不是并且会导致麻烦。



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


I wonder if there is a possibility to eager load related entities for certain subclass of given class.

Class structure is below

Order has relation to many base suborder classes (SuborderBase). MySubOrder class inherits from SuborderBase. I want to specify path for Include() to load MySubOrder related entities (Customer) when loading Order, but I got an error claiming that there is no relation between SuborderBase and Customer. But relation exists between MySubOrder and Customer.

Below is query that fails

Context.Orders.Include("SubOrderBases").Include("SubOrderBases.Customers")

How can I specify that explicitly?

Update. Entity scheme is below

解决方案

This is a solution which requires only a single roundtrip:

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();

It is basically a projection into an anonymous type collection. Afterwards the query result is transformed into entities and navigation properties in memory. (It also works with disabled tracking.)

If you don't need entities you can omit the whole part after the first ToList() and work directly with the result in the anonymous objects.

If you must modify this object graph and need change tracking, I am not sure if this approach is safe because the navigation properties are not completely set when the data are loaded - for example MyOrder.Customers is null after the projection and then setting relationship properties in memory could be detected as a modification which it isn't and cause trouble when you call SaveChanges.

Projections are made for readonly scenarios, not for modifications. If you need change tracking the probably safer way is to load full entities in multiple roundtrips as there is no way to use Include in a single roundtrip to load the whole object graph in your situation.

这篇关于实体框架 - 加载子类相关对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆