10

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 enter image description here

3
  • 1
    Probably no solution with eager loading. Here is a workaround with a projection (only the third code snippet in accepted answer works, not the second snippet, see comments to the answer): stackoverflow.com/questions/6586574/…. Here (stackoverflow.com/questions/7203303/…) was a similar question with no answer at all. Commented Oct 3, 2011 at 13:08
  • Can you sketch the classes and relationships briefly in code (Order, SubOrderBase, MySubOrder, Customer)? Looking at the answers people seem to misunderstand your question. I'm getting unsure as well now after first answers and comments. Commented Oct 3, 2011 at 13:28
  • Added picture with class diagram Commented Oct 3, 2011 at 13:49

2 Answers 2

13

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! very interesting solution! Not exactly what i wanted, but i think this example will be a great inspiration
Great answer but what a remarkably daft way of having to do things. Anyone would think that the EF team overlooked the fact that relational databases have relationships between tables.
0

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

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

and the same for the customers..

1 Comment

try this: Context.Orders.Include("SubOrderBases").Include("Customers")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.