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має спрацювати, якщо ви не маєте на увазі, що додатковим фактором є онук Курса. Побачити це, або кращий варіант, це такий
— фон проти

Відносяться / можливо дублікат 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 та перегляньте зразки. Я думаю, що це найшвидший спосіб познайомитись з Лінком та Ламбдою.

На початку - різниця між Selectі Includeтака, що з Select ви вирішили , що ви хочете , щоб повернутися (він же проекції). Функція "Включити" - це функція швидкого завантаження , яка повідомляє 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для доступу до методу розширення. Більше інформації тут
— Jens Kloster

using System.Data.Entity;зробив це. Дякую!
— Джо Смо

1
наголосили на згадці про блискучий linqpad та підказку щодо використання System.Data.Entity, thx Jens
— Майк

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 inside .Include. Чи може хтось підтвердити чи поговорити?
— ttugates

@ttugates Що ви збираєтесь робити з цим вибором? Я думаю, що ти хочеш зробити саме те, що ти робиш ThenIncludeв ядрі EF. Можливо, складіть запитання з хорошим прикладом, щоб ми могли відповісти на нього.
— Нік Н.

@ Nick N - Entity Framework Linq Query: How to Where on Multi Nev Properties and Select from 3rd Nav Properties . Оскільки те, що я вибираю, - це не те, на що я відповідаю, Включає не потрібно, тому питання є дотичним. Моє запитання може бути занадто вузьким, але вдячний за будь-яку допомогу.
— ttugates

1
Ага. Насправді .ThenInclude () працює. Просто потрібно назавжди для інтелігенції для відображення відповідних таблиць.
— Кріс Дж

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);

Я намагався відповісти, але це кидає stackoverflowexceptions через нескінченний цикл із собою.
— Вікторія С.

1
@VictoriaS., Ви можете перейменувати метод розширення, щоб він не заважав реальномуInclude
— Mohsen Afshin
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.