EF LINQ включает в себя несколько и вложенные объекты

155

Хорошо, у меня есть трехуровневые объекты со следующей иерархией: Курс -> Модуль -> Глава

Вот оригинальное заявление EF LINQ:

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

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

Как включить объект «Лаборатория»?

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

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

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

Любой совет или информацию будут высоко оценены. Спасибо!

AnimaSola
источник
1
Добавление другого .Includeдолжно работать, если вы не имеете в виду, что дополнительное включение - это, конечно, внук. Посмотрите это или лучший вариант это
von v.
Связанный / возможный дубликат stackoverflow.com/q/3356541
StuartLC

Ответы:

234

Вы пробовали просто добавить еще один 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, что вы хотите, чтобы она включала данные из других таблиц.

Синтаксис включения также может быть в строке. Как это:

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

Но примеры в LinqPad объясняют это лучше.

Йенс Клостер
источник
Ценить это! Где я могу узнать больше об этом? Меня особенно интересует разница между Включить и Выбрать
AnimaSola
3
Только этот работал для меня .Include("Module.Chapter"). Есть идеи, почему это так?
Джо Смо
5
@JoSmo вам нужно импортировать пространство имен System.Data.Enityдля доступа к методу расширения. больше информации здесь
Дженс Клостер
using System.Data.Entity;сделал это. Спасибо!
Джо Смо
1
проголосовал за упоминание о блестящем linqpad и советы по использованию System.Data.Entity, спасибо Дженс
Майк
38

В Entity Framework Core ( 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()включение 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();
Ник Н.
источник
В EF.core я, кажется, не могу сделать .Include (i => i.Modules.Select (s => s.Chapters)), в частности .Select внутри .Include. Кто-нибудь может подтвердить или поговорить?
ttugates
@ttugates Что вы собираетесь делать с этим выбором? Я думаю, что вы хотите сделать именно то, что вы делаете ThenIncludeв ядре EF. Возможно, составьте вопрос с хорошим примером, чтобы мы могли на него ответить.
Ник Н.
@Nick N - Entity Framework Linq Query: как найти несколько свойств Nav и выбрать из третьего свойства Nav . Поскольку то, что я выбираю, не совпадает с тем, с которым я сопоставляюсь, включения не нужны, поэтому вопрос является касательным. Мой вопрос может быть слишком "узким", но я ценю любую помощь.
ttugates
1
Ах. На самом деле .ThenInclude () работает. Просто требуется навсегда для intellisense для отображения связанных таблиц.
Крис Дж
23

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

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 
Илья Иванов
источник
ценить это! не могли бы вы указать мне, где я могу узнать больше об этом? Спасибо!
AnimaSola
1
Знаете ли вы, каков синтаксис, если у модулей есть несколько таблиц, к которым вы хотите присоединиться? Скажите это ссылки на главы и что-то еще?
Дэвид Спенс
Свободно ли является частью .Net или это библиотека, которую нужно установить?
Codea
19

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

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
Мартин Ларссон
источник
4
Спасибо - точечная запись в строке очень полезна
Evert
1
Это может быть полезно, но одной из причин не использовать это является простота рефакторинга позже: если в какой-то момент вы переименуете сущность «Главы», другой пример будет автоматически переименован. Другое - ошибки будут обнаружены раньше: во время компиляции, а не во время выполнения.
MGOwen
2

Можно написать метод расширения следующим образом:

    /// <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);
Мохсен Афшин
источник
Я пробовал ваш ответ, но он генерирует исключения stackoverflow из-за бесконечного цикла с самим собой.
Виктория С.
1
@VictoriaS., Вы можете переименовать метод расширения, чтобы он не мешал реальномуInclude
Мохсен Афшин