[C#] 엔터티 프레임 워크-여러 수준의 속성 포함

Include () 메서드는 객체의 목록에 매우 적합합니다. 하지만 두 단계 더 깊이 가야한다면 어떻게해야합니까? 예를 들어, 아래 메소드는 여기에 표시된 특성이 포함 된 ApplicationServer를 리턴합니다. 그러나 ApplicationsWithOverrideGroup은 다른 복잡한 개체를 보유하는 또 다른 컨테이너입니다. 해당 속성에 대해 Include ()를 수행 할 수 있습니까? 또는 해당 속성을 완전히로드하려면 어떻게해야합니까?

현재이 방법은 다음과 같습니다.

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

Application 또는 CustomVariableGroup 속성 (아래)이 아닌 Enabled 속성 (아래) 만 채 웁니다. 어떻게하면 되나요?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
    public bool Enabled { get; set; }
    public Application Application { get; set; }
    public CustomVariableGroup CustomVariableGroup { get; set; }
}



답변

EF 6

using System.Data.Entity;

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

람다에 필요한 using System.Data.Entity;버전을 얻으려면 추가해야합니다 Include.


EF 코어

새로운 방법을 사용하십시오 ThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);


답변

올바르게 이해하면 중첩 속성을 포함시키는 것이 좋습니다. 그렇다면 :

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

또는

.Include("ApplicationsWithOverrideGroup.NestedProp")  

또는

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}")  


답변

EF Core : “ThenInclude”를 사용하여 여러 레벨로드 : 예 :

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ThenInclude(author => author.Photo)
    .ToList();


답변

하위 엔터티를 좋은 방식으로 포함시키기 위해 Entity Framework 6 (.Net Core 스타일)에 대한 작은 도우미를 만들었습니다.

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에서 사용할 수 있습니다 .


답변

MSDN에 대한 더 많은 EFCore 예제Includeand를 사용 하여 매우 복잡한 작업을 수행 할 수 있음을 보여줍니다 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 실제로 엔티티를 편집하고 다시 저장하지 않으려는 경우 작업 속도를 크게 높일 수 있습니다.


답변

또한 여러 포함을 사용해야했고 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();

이것은 누군가를 도울 수 있습니다 🙂


답변

문자열 리터럴을 사용하는 것이 마음에 들지 않으면 해당 관계의 다중성에 관계없이 문자열 오버로드를 사용하여 중첩 레벨을 포함시킬 수 있음을 분명히 밝힙니다.

query.Include("Collection.Property")