Entity framework linq query Include () несколько дочерних сущностей
Это может быть действительно элементарный вопрос, но какой хороший способ включить несколько дочерних сущностей при написании запроса, который охватывает три уровня (или более)?
т. е. у меня есть 4 таблицы: Company,Employee,Employee_Car и Employee_Country
компания имеет отношение 1:m с работником.
сотрудник имеет отношение 1:m как с Employee_Car и Employee_Country.
если я хочу написать запрос, который возвращает данные из всех 4 столах, я в настоящее время пишу:
Company company = context.Companies
.Include("Employee.Employee_Car")
.Include("Employee.Employee_Country")
.FirstOrDefault(c => c.Id == companyID);
там должен быть более элегантный способ! Это долго наматывается и генерирует ужасный SQL
Я использую EF4 с VS 2010
4 ответов:
использовать методы расширения. Заменить NameOfContext С именем контекста объекта.
public static class Extensions{ public static IQueryable<Company> CompleteCompanies(this NameOfContext context){ return context.Companies .Include("Employee.Employee_Car") .Include("Employee.Employee_Country") ; } public static Company CompanyById(this NameOfContext context, int companyID){ return context.Companies .Include("Employee.Employee_Car") .Include("Employee.Employee_Country") .FirstOrDefault(c => c.Id == companyID) ; } }тут код
Company company = context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID); //or if you want even more Company company = context.CompanyById(companyID);
EF 4.1 - EF 6
есть типизированы
.Includeчто позволяет указать необходимую глубину нетерпеливой загрузки, предоставив выбранные выражения на соответствующую глубину:using System.Data.Entity; // NB! var company = context.Companies .Include(co => co.Employees.Select(emp => emp.Employee_Car)) .Include(co => co.Employees.Select(emp => emp.Employee_Country)) .FirstOrDefault(co => co.companyID == companyID);Sql, созданный в обоих случаях, по-прежнему не является интуитивно понятным, но кажется достаточно производительным. Я поставил небольшой пример на GitHub здесь
EF Core
ядро EF имеет новый метод расширения,
.ThenInclude(), хотя синтаксис немного разные:var company = context.Companies .Include(co => co.Employees) .ThenInclude(emp => emp.Employee_Car) ...согласно документам, я бы сохранил дополнительный "отступ" в
.ThenIncludeсохранить ваше здравомыслие.устаревшая информация (не делайте этого):
загрузка нескольких внуков может быть сделано за один шаг, но это требует довольно неудобного разворота вверх по графику, прежде чем отправиться вниз по следующему узлу (NB: это делает Не работать с
AsNoTracking()- вы получите ошибку времени выполнения):var company = context.Companies .Include(co => co.Employees .Select(emp => emp.Employee_Car .Select(ec => ec.Employee) .Select(emp2 => emp2.Employee_Country))) .FirstOrDefault(co => co.companyID == companyID);поэтому я бы остался с первым вариантом (один включает в себя модель глубины объекта leaf).
вы можете найти эту интересную статью, которая доступна по адресу codeplex.com.
в статье представлен новый способ выражения запросов, которые охватывают несколько таблиц в виде декларативных форм графа.
кроме того, статья содержит тщательное сравнение производительности этого нового подхода с запросами EF. Этот анализ показывает, что GBQ быстро превосходит запросы EF.
другого пути нет-кроме реализации ленивой загрузки.
или ручная загрузка....
myobj = context.MyObjects.First(); myobj.ChildA.Load(); myobj.ChildB.Load(); ...
Comments