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);
Любые идеи о включении второго объекта?
Любая рекомендация или информация будут высоко оценены. Спасибо!
Ответы
Ответ 1
Вы пробовали просто добавить еще один 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 выберите , что, которое вы хотите вернуть (aka projection). Include - это функция Eager Loading, которая сообщает Entity Framework, что вы хотите, чтобы она включала данные из других таблиц.
Синтаксис Include также может быть в строке. Вот так:
db.Courses
.Include("Module.Chapter")
.Include("Lab")
.Single(x => x.Id == id);
Но образцы в LinqPad объясняют это лучше.
Ответ 2
Include
является частью свободного интерфейса, поэтому вы можете писать несколько операторов Include
, которые следуют за другими
db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
.Include(i => i.Lab)
.Single(x => x.Id == id);
Ответ 3
Вы также можете попробовать
db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
Ответ 4
В 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
Ответ 5
Можно написать способ расширения следующим образом:
/// <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);