34

Given the object hierarchy

public class Parent
{
    public int Id { get; set; }
    public virtual Child Child { get; set; }
}

public class Child
{
    public int Id { get; set; }
    public virtual GrandChild GrandChild { get; set; }
}

public class GrandChild
{
    public int Id { get; set; }
}

and the DB context

public class MyContext : DbContext
{
    public DbSet<Parent> Parents { get; set; }
}

One can include children and grandchildren using Lambda syntax (using System.Data.Entity) like this:

using (MyContext ctx = new MyContext())
{
    var hierarchy = 
        from p in ctx.Parents.Include(p => p.Child.GrandChild) select p;
}

The Lambda syntax prevents breaking the query if the class names are subsequently altered. However, if Parent has an ICollection<Child> like this instead:

public class Parent
{
    public int Id { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}

Lambda syntax no longer works. Instead, one can use the string syntax:

var hierarchy = from p in ctx.Parents.Include("Children.GrandChild") select p;

Is the string syntax the only option, or is there some alternative way to use Lambda syntax in this situation?

Romano Zumbé
  • 7,893
  • 4
  • 33
  • 55
Eric J.
  • 147,927
  • 63
  • 340
  • 553

2 Answers2

45

Update: If you are using Entity Framework Core you should use the following syntax

var hierarchy = from p in ctx.Parents
                    .Include(p => p.Children)
                    .ThenInclude(c => c.GrandChild)
                select p;
TWI
  • 575
  • 5
  • 12
  • 10
    Note: In my case, for some weird reason intellisense wouldn't prompt me with the Grandchild object in the ".ThenInclude" lambda clause, but this was an edge case where intellisense was wrong and it didn't matter - the code still compiled. – Ben Barreth Oct 27 '17 at 14:14
  • 1
    What if you need to include the children of the GrandChild (aka GrandGrandChild)? – Julen Apr 08 '19 at 10:14
  • 3
    @Julen you can use .ThenInclude recursively for every nested child entity, like this: Parent.Include(child).ThenInclude(GrandChild).ThenInclude(GrandGrandChild) .. etc – Mohamed Nagieb Jun 02 '19 at 11:40
  • 5
    How would you include two different grandchildren, say GrandSon and GrandDaughter? Something starting like `ctx.Parents.Include(p => p.Children).ThenInclude(c => c.GrandSon)...`. You couldn't add `ThenInclude(c => c.GrandDaughter)` because it would look in the GrandSon object for the GrandDaughter. – Simon Elms Nov 22 '19 at 05:24
  • 4
    @SimonTewsi unfortunately the only way to do it right now is to `.Include` the top level a second time, then do another `.ThenInclude` with the other child you want to include. – stjns Jan 02 '20 at 16:41
42

Sure, you can do

var hierarchy = from p in ctx.Parents
                    .Include(p => p.Children.Select(c => c.GrandChild))
                select p;

See MSDN, caption Remarks, the fifth bullet.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291