Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IQueryable<T>.Include() gets ignored

I have Parent and Child entities related to each other as 1 to M. I need to query childs together with parents within a single SQL query, but the Include method is not properly working for some cases.
This one makes a correct single query for both Parent and Child tables (via JOIN):

var r1 =
    ctx.Set<Parent>()
       .Include(p => p.Childs)
       .Where(p => p.Id == 1)
       .ToList();

Once i create an anonymous object on the fly, children are getting lost and SQL contains only Parent's fields. Retrieval of children remains lazy - they are still not loaded:

var r2 =
    ctx.Set<Parent>()
       .Include(p => p.Childs)
       .Where(p => p.Id == 2)
       .Select(p => new { myParent = p})
       .ToList();

Questions:

  1. Why it's so?
  2. How can I construct a new anonymous object in my LINQ so childs are not geting lost?

p.s. i'd like keep Childs property of Parent virtual.

like image 255
LINQ2Vodka Avatar asked Mar 08 '14 11:03

LINQ2Vodka


1 Answers

This is a general problem in all versions of EF known to me. EF tries hard to pass the 'includes' as far as possible, but when "the shape of the query changes", the 'includes' are irreversibly lost.

The "shape" of the query changes for example, when:

  • a projection is used (select not whole object but just some fields, or different object)
  • a group-by or other aggregation is used
  • .. and probably in some more cases, which currently I dont remember.

Sadly, I also dont remember where on MSDN I stumbled upon the "shape of the query" explanation. If I find it, I'll drop here a link.

The solution is actually quite simple: simply specify the 'include' part not early, but at the final result. So, instead of set.include(x) at beginning, do .Select( .. => new { .., x }) to include the 'x' manually. It also works during grouping, as you can do a projection there too.

However, this is not a solution. This is a manual patch/hotfix, which does not solve anything. Considering that you might want to expose a "IQueryable<>" through some interface, you may like to expose a "base query" with some things already .Included. And of course, this is simply not possible to do in a general way, as if the client of the interface does a projection or grouping, he will lose the includes and he will not even know which ones should be. For me, this is a major deficiency in EF.

EDIT: just found one: .Include in following query does not include really Not MSDN, but just as good.

like image 103
quetzalcoatl Avatar answered Nov 07 '22 17:11

quetzalcoatl