Include vs. ThenInclude for grandchild properties in EF Core

Viewed 291

Is one of these approaches preferred for loading grandchildren properties? I like how succinct the first is, but I don't know if it's more costly.

return source
    .Include(x => x.Server)
    .Include(x => x.Server.User)
    .Include(x => x.Server.ParentServer)
    .Include(x => x.Server.DataCenter);

or

return source
    .Include(x => x.Server)
        .ThenInclude(s => s.User)
    .Include(x => x.Server)
        .ThenInclude(s => s.ParentServer)
    .Include(x => x.Server)
        .ThenInclude(s => s.DataCenter);
2 Answers

They are equivalent. The first one is obviously preferred, but it's not possible with collection navigations. Hence, ThenInclude().

// Won't compile
return source
    .Include(x => x.Posts.Authors)
    .Include(x => x.Posts.Comments);

// Compiles
return source
    .Include(x => x.Posts)
        .ThenInclude(x => x.Authors)
    .Include(x => x.Posts)
        .ThenInclude(x => x.Comments);

But, if you want to give up compile-time type safety, you can also just use the string overloads.

// Compiles, may throw
return source
    .Include("Posts.Authors")
    .Include("Posts.Comments");

But please, don't do this...

// Over-thinking it ;-)
return source
    .Include(nameof(Blog.Posts) + "." + nameof(Post.Authors))
    .Include(nameof(Blog.Posts) + "." + nameof(Post.Comments));

That's a very interesting question ! This point isn't documented at all if EF (Core) docs.

A few weeks ago I ran some tests about this and my conclusion was that there's no difference between those methods.

I tried dozens of scenarios, from the simplest and dumbest ones to a 8 level relations hierarchy, and the generated SQL request were always 100% identical.

Then I had a look EF Core's source code and found no real differences between Include() and ThenInclude() implementations.

So my answer is not 100% affirmative, maybe I'm missing something, but, I think that both methods are identical.

If you want a definitive answer, I think that the best way is to ask your question on EF Core's repo.

Related