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-й сущности?

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


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
— Мохсен Афшин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.