开发者

Entity Framework - Eager loading of subclass related objects

开发者 https://www.devze.com 2023-04-10 12:15 出处:网络
I wonder if there is a possibility to eager load related entities for certain subclass of given class.

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 (Su开发者_StackOverflow社区borderBase). 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

Entity Framework - Eager loading of subclass related objects


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.


Suppose u loaded the orders list as lstOrders, try this:

foreach (Orders order in lstOrders)
    order.SubOrderBases.Load();

and the same for the customers..

0

精彩评论

暂无评论...
验证码 换一张
取 消