Вопрос по entity-framework, c# – Entity Framework - включает несколько уровней свойств

294

Метод Include () хорошо работает для списков объектов. Но что, если мне нужно пройти два уровня? Например, метод ниже вернет ApplicationServers с включенными свойствами, показанными здесь. Однако ApplicationsWithOverrideGroup - это другой контейнер, который содержит другие сложные объекты. Могу ли я сделать функцию Include () для этого свойства? Или как я могу получить это свойство для полной загрузки?

As it stands now, this method:

public IEnumerable<ApplicationServer> GetAll()
{
    return this.Database.ApplicationServers
        .Include(x => x.ApplicationsWithOverrideGroup)                
        .Include(x => x.ApplicationWithGroupToForceInstallList)
        .Include(x => x.CustomVariableGroups)                
        .ToList();
}

Заполняет только свойство Enabled (ниже), но не свойства Application или CustomVariableGroup (ниже). Как мне это сделать?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
    public bool Enabled { get; set; }
    public Application Application { get; set; }
    public CustomVariableGroup CustomVariableGroup { get; set; }
}
Привет, почему я получаю исключениеExpression must be a member expression когда я пытаюсь это сделать: включить коллекцию, а затем коллекцию на один уровень ниже:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection)). Joe.wang
@BobHorn, у меня та же проблема. В моем случае, вложенность идет глубоко в несколько слоев, мне удалось сделать то, что вы указали. В сгенерированном SQL я мог видеть, что все столбцы возвращаются с разными псевдонимами, как c1, c2 и так далее. Мой вопрос заключается в том, как я могу сформировать вложенную коллекцию DTO из всех моих включений :(. Может быть, вы можете взять сам пример выше, так как мы возвращаем все столбцы без какого-либо пользовательского DTO (который сам по себе является коллекцией DTO & apos)? с); TechQuery

Ваш Ответ

7   ответов
2

что вы можете использовать перегрузку строки для включения вложенных уровней независимо от кратности соответствующих отношений, если вы не возражаете против использования строковых литералов:

query.Include("Collection.Property")
9

EFCore примеры на MSDN показать, что вы можете делать довольно сложные вещи сInclude а такжеThenInclude.

Это хороший пример того, насколько сложным вы можете стать (это все одно утверждение!):

viewModel.Instructors = await _context.Instructors

      .Include(i => i.OfficeAssignment)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Enrollments)
                .ThenInclude(i => i.Student)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Department)

      .AsNoTracking()
      .OrderBy(i => i.LastName)
      .ToListAsync();

Посмотрите, как вы можете цепиInclude даже послеThenInclude и это как бы «сбрасывает» Вы возвращаетесь на уровень сущности высшего уровня (Инструкторы).

Вы даже можете повторить тот же «первый уровень» Коллекция (CourseAssignments) несколько раз с последующим отдельнымThenIncludes Команды, чтобы добраться до разных дочерних объектов.

Обратите внимание, что ваш фактический запрос должен быть помечен в концеInclude или жеThenIncludes цепь. Следующее НЕ работает:

var query = _context.Instructors.AsQueryable();
query.Include(i => i.OfficeAssignment);

var first10Instructors = query.Take(10).ToArray();

Настоятельно рекомендую настроить ведение журнала и убедиться, что ваши запросы не вышли из-под контроля, если вы включаете более одной или двух вещей. Важно видеть, как это на самом деле работает, и вы заметите, что каждое отдельное включает и включает. обычно это новый запрос, чтобы избежать массивных объединений, возвращающих избыточные данные.

AsNoTracking может значительно ускорить процесс, если вы не собираетесь на самом деле редактировать объекты и сохранять их.

Есть ли способ получить и зачисление, и зачисление в департаменты без повторного. Включая назначение курса и курса? (До сих пор кажется, что Api может пойти глубже с .ThenInclude или вернуться на верхний уровень с помощью .Include, но ничего не остается на том же уровне?)
Если вы хотите ленивой загрузки, следите за обновлениями для EF Core 2.1blogs.msdn.microsoft.com/dotnet/2018/02/02/… но если вы просто хотите загрузить больше на том же уровне, я думаю, что это дизайн. Я не уверен, о чем вы думаете, - для этого не требуется много дополнительных усилий, и это значительно уменьшает то, что возвращается из базы данных. Сущность может иметь только один или два «одинакового уровня»; вещей, но это может также иметь 50 для большого проекта, будучи явным делает ваше приложение намного быстрее.
15

и на 3-м уровне мне нужно было несколько свойств

(from e in context.JobCategorySet
                      where e.Id == id &&
                            e.AgencyId == agencyId
                      select e)
                      .Include(x => x.JobCategorySkillDetails)
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.DurationType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RuleType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RateType))
                      .FirstOrDefaultAsync();

Это может кому-то помочь :)

ну, это зависит от того, как глубоко вы хотите пойти
это можно сделать без повторения.Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt......
559

For EF 6


query.Include(x => x.Collection.Select(y => y.Property))

Увидетьзамечания для большего количества примеров.

Обязательно добавьте чтобы получить версиюInclude это берет в лямбду.

For EF Core

Используйте новый методThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);
@ Адем тебе нужно позвонитьInclude для каждого свойства:Db.States.Include(state => state.Cities.Select(city => city.Customers).Include(state => state.Cities.Select(city => city.Vendors)
Я не могу использовать ваши правки, потому что ApplicationsWithOverrideGroup - это список. Приложение - это свойство каждого элемента в списке, а не самого списка. Bob Horn
Я не могу сделать Include () для ApplicationsWithOverrideGroup. Он не отображается в значении intellisense. Bob Horn
Не забудьте включить System.Data.Entity в употребления. В противном случае Intellisense предоставит вам только версию метода (строка пути).
Аааа, но та ссылка, которую вы предоставили, кажется, дает ответ. Позвольте мне попробовать это: включить коллекцию, а затем коллекцию на один уровень ниже: query.Include (e = & gt; e.Level1Collection.Select (l1 = & gt; l1.Level2Collection)). Bob Horn
36

EF Core:  ThenInclude & quot; загрузить несколько уровней: Например:

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ThenInclude(author => author.Photo)
    .ToList();
К вашему сведению: VS2017 Intellisense не работал для .ThenInclude. Просто введите его так, как вы думаете, и подсветка ошибок должна исчезнуть.
Похоже, это только EF Core
Я хочу подчеркнуть комментарий @JohnWrensby: Intellisense иногда может занять особенно много времени для обработки ThenInclude, это может быть довольно запутанным для новых пользователей. У меня также были случаи, когда простое лямбда-выражение «Включить» обрабатывалось неправильно, пока вы просто не набрали его и не скомпилировали, игнорируя «ошибки». показано в VS.
55

вы спрашиваете о включении вложенных свойств. Если так :

.Include(x => x.ApplicationsWithOverrideGroup.NestedProp)

или же

.Include("ApplicationsWithOverrideGroup.NestedProp")  

или же

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}")  
Вы были близки Я, возможно, не ясно, что ApplicationsWithOverrideGroup был список. Спасибо за помощь! Bob Horn
Не забудьте включитьSystem.Data.Entity в употреблениях. В противном случае Intellisense даст вам толькоInclude(string path) версия метода.
Спасибо, я могу попробовать это. Я надеялся, что смогу держать вещи строго напечатанными и избежать строковых литералов. Но если это так, как это должно быть сделано ... Bob Horn
@Judo, у меня та же проблема .. В моем случае, вложенность идет глубоко в несколько слоев, мне удалось сделать включение, которое вы указали. В сгенерированном SQL я мог видеть, что все столбцы возвращаются с разными псевдонимами, как c1, c2 и так далее. Мой вопрос заключается в том, как я могу сформировать вложенную коллекцию DTO из всех моих включений :(. Может быть, вы можете взять сам пример выше, так как мы возвращаем все столбцы без какого-либо пользовательского DTO (который сам по себе является коллекцией DTO & apos)? с);
23

чтобы красиво включать под-сущности.

Сейчас на NuGet: Install-Package ThenInclude.EF6

using System.Data.Entity;

var thenInclude = context.One.Include(x => x.Twoes)
    .ThenInclude(x=> x.Threes)
    .ThenInclude(x=> x.Fours)
    .ThenInclude(x=> x.Fives)
    .ThenInclude(x => x.Sixes)
    .Include(x=> x.Other)
    .ToList();

Пакетдоступно на GitHub.

@ lenny32 что-нибудь знать об этом расширении?
привет, у меня есть исключение во время выполнения, я не могу привести IncludableQueryable & lt; observablecollection & gt; в IncludableQueryable & lt; genericcollection & gt;
Сначала я использую db, и я изменил файл tt, чтобы получить ObservableCollections для всех моих сущностей, любая помощь приветствуется.

Похожие вопросы