168

Ok, I have tri-leveled entities with the following hierarchy: Course -> Module -> Chapter

Here was the original EF LINQ statement:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Single(x => x.Id == id); 

Now, I want to include another entity called Lab which is associated with a course.

How do I include the Lab entity?

I tried the following but it didn't work:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters) && i.Lab)
                .Single(x => x.Id == id); 

Any ideas on including the 2nd Entity?

Any piece of advise or information would be highly appreciated. Thanks!

AnimaSola
  • 5,436
  • 13
  • 38
  • 58
  • 1
    Adding another `.Include` should work unless you mean that the additional include is a grandchild of Course. [See this](http://stackoverflow.com/questions/3356541/entity-framework-linq-query-include-multiple-children-entities) or a [better option is this](http://stackoverflow.com/questions/13819856/entity-framework-5-multiple-include-is-this-possible) – von v. Apr 02 '13 at 12:55
  • Related / possible duplicate of https://stackoverflow.com/q/3356541 – StuartLC Aug 06 '18 at 10:35

6 Answers6

245

Have you tried just adding another Include:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Include(i => i.Lab)
                .Single(x => x.Id == id);

Your solution fails because Include doesn't take a boolean operator

Include(i => i.Modules.Select(s => s.Chapters) &&          i.Lab)
                           ^^^                  ^             ^ 
                          list           bool operator    other list

Update To learn more, download LinqPad and look through the samples. I think it is the quickest way to get familiar with Linq and Lambda.

As a start - the difference between Select and Include is that that with a Select you decide what you want to return (aka projection). The Include is a Eager Loading function, that tells Entity Framework that you want it to include data from other tables.

The Include syntax can also be in string. Like this:

           db.Courses
            .Include("Module.Chapter")
            .Include("Lab")
            .Single(x => x.Id == id);

But the samples in LinqPad explains this better.

J Bryan Price
  • 1,204
  • 10
  • 16
Jens Kloster
  • 10,267
  • 4
  • 36
  • 51
  • Appreciate it! Where can I learn more of this? I'm especially interested in the difference between Include and Select – AnimaSola Apr 03 '13 at 02:37
  • 3
    Only this one worked for me: `.Include("Module.Chapter")`. Any idea why would that be? – Jo Smo Aug 02 '15 at 17:19
  • 5
    @JoSmo you need to import the namespace `System.Data.Enity` to access the extensionmethod. more info [here](https://msdn.microsoft.com/en-us/library/gg671236%28v=vs.103%29.aspx) – Jens Kloster Aug 02 '15 at 18:37
  • `using System.Data.Entity;` did it. Thanks! – Jo Smo Aug 03 '15 at 18:06
  • You might need to disable lazy loading to avoid infinite loop errors: `dbContext.Configuration.LazyLoadingEnabled = false;` – Sean Apr 18 '16 at 09:24
  • 1
    upvoted for mentioning the brilliant linqpad, and tip to use System.Data.Entity, thx Jens – Mike Aug 31 '16 at 09:36
53

In Entity Framework Core (EF.core) you can use .ThenInclude for including next levels.

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .ToList();

More information: https://docs.microsoft.com/en-us/ef/core/querying/related-data

Note: Say you need multiple ThenInclude() on blog.Posts, just repeat the Include(blog => blog.Posts) and do another ThenInclude(post => post.Other).

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Other)
 .ToList();
Nick N.
  • 10,720
  • 4
  • 50
  • 70
  • In EF.core I seem to not be able to do .Include(i => i.Modules.Select(s => s.Chapters)), specifically the .Select inside .Include. Can anyone confirm or speak to? – ttugates Dec 16 '17 at 13:43
  • @ttugates What do you intent to do with this select? I think what you want to do is exactly what you do with `ThenInclude` in EF core. Perhaps make a question with a good example, so that we can answer it. – Nick N. Dec 18 '17 at 14:05
  • [@Nick N](https://stackoverflow.com/users/869033/nick-n) - [Entity Framework Linq Query: How to Where on Multiple Nav Properties and Select from 3rd Nav Property](https://stackoverflow.com/questions/47870578/entity-framework-linq-query-how-to-where-on-multiple-nav-properties-and-select). Because what I Select is not what I am matching on, the Includes are not necessary so the question is tangential. My question may be too "narrow" but appreciate any help. – ttugates Dec 18 '17 at 14:32
  • 1
    Ah. Actually, .ThenInclude() does work. Just takes forever for the intellisense to display the related tables. – Chris J Jan 10 '19 at 23:24
24

Include is a part of fluent interface, so you can write multiple Include statements each following other

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 
Ilya Ivanov
  • 22,043
  • 4
  • 58
  • 86
22

You can also try

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
Martin Larsson
  • 690
  • 2
  • 9
  • 20
  • 4
    Thanks - the dot notation in the string very useful – Evert Sep 10 '15 at 13:39
  • 2
    This can be useful, but, one reason not to use this is ease of refactoring later: if you rename the "Chapters" entity at some point, the other example will automatically be renamed. Another is that errors will be found sooner: at compile time, not run time. – MGOwen Apr 14 '20 at 02:45
  • 2
    @MGOwen I agree with your comment. However, could use: `db.Courses.Include($"{nameof(Modules)}.{nameof(Chapters)}").Single(c => c.Id == id);` as well. – Zze Aug 30 '20 at 22:15
5

One may write an extension method like this:

    /// <summary>
    /// Includes an array of navigation properties for the specified query 
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <param name="query">The query to include navigation properties for that</param>
    /// <param name="navProperties">The array of navigation properties to include</param>
    /// <returns></returns>
    public static IQueryable<T> Include<T>(this IQueryable<T> query, params string[] navProperties)
        where T : class
    {
        foreach (var navProperty in navProperties)
            query = query.Include(navProperty);

        return query;
    }

And use it like this even in a generic implementation:

string[] includedNavigationProperties = new string[] { "NavProp1.SubNavProp", "NavProp2" };

var query = context.Set<T>()
.Include(includedNavigationProperties);
Mohsen Afshin
  • 12,711
  • 8
  • 63
  • 84
2

this is from my project

 var saleHeadBranch = await _context.SaleHeadBranch
 .Include(d => d.SaleDetailBranch)
 .ThenInclude(d => d.Item)
 .Where(d => d.BranchId == loginTkn.branchId)
 .FirstOrDefaultAsync(d => d.Id == id);
  • Thanks for taking the time to contribute an answer.! Can you:- 1) edit your answer so the answer in detail. 2) Explain what you are trying to achieve with this answer and what you want to say.? See How do I write a good answer in the Help Centre for more information (How to Ask : https://stackoverflow.com/help/how-to-answer) – Paresh Mangukiya Oct 03 '20 at 14:00
  • var saleHeadBranch = await _context.SaleHeadBranch .Include(d => d.SaleDetailBranch) .Include("SaleDetailBranch.Item") .Where(d => d.BranchId == loginTkn.branchId) .FirstOrDefaultAsync(d => d.Id == id); – Rameesh Puthukkudy Oct 27 '20 at 13:21