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.