EF LINQ включает в себя несколько вложенных сущностей


хорошо, у меня есть трехуровневые сущности со следующей иерархией: курс - > модуль - > глава

здесь было оригинальное заявление EF LINQ:

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

теперь я хочу включить еще один объект, называемый Lab, который связан с курсом.

Как включить объект Lab?

я попробовал следующее, Но это не сработало:

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

есть идеи по включению 2-й сущности?

любая часть советует или информации был бы весьма признателен. Спасибо!

5 130

5 ответов:

вы пробовали просто добавить еще один Include:

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

ваше решение терпит неудачу, потому что Include не принимает логический оператор

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

обновление Чтобы узнать больше, загрузите LinqPad и посмотреть образцы. Я думаю, что это самый быстрый способ познакомиться с Linq и Lambda.

для начала-разница между Select и Include это то, что с выбором вы решаете что вы хотите вернуться (ака проекция). Включить это Предвыборка функция, которая сообщает Entity Framework, что вы хотите, чтобы она включала данные из других таблиц.

синтаксис Include также может быть в строке. Вот так:

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

но образцы в LinqPad объясняет это лучше.

Include является частью интерфейса, так что вы можете записать несколько Include утверждения друг за другом

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

вы также можете попробовать

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);

В Ядре Entity Framework (EF.core) можно использовать .ThenInclude для включения следующего уровня.

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

дополнительная информация:https://docs.microsoft.com/en-us/ef/core/querying/related-data

Примечание: Скажем, вам нужно несколько ThenInclude() on blog.Posts повторить Include(blog => blog.Posts) и сделать еще 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();

можно написать метод расширения, как это:

    /// <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;
    }

и использовать его так даже в общей реализации:

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

var query = context.Set<T>()
.Include(includedNavigationProperties);