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

714   4  

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.

Как построить запрос LINQ to Entities для прямой загрузки дочерних объектов, вместо вызова ссылочного свойства или Load ()

другого пути нет-кроме реализации ленивой загрузки.

или ручная загрузка....

myobj = context.MyObjects.First();
myobj.ChildA.Load();
myobj.ChildB.Load();
...

Comments

    Ничего не найдено.