7

이 질문의 두 번째 단계는 here (EF 4.1 code-first: How to load related data (parent-child-grandchild)?)입니다. @Slauma 님의 안내에 따라 데이터를 검색 할 수있었습니다. 그것은이 데이터베이스에 대해 많은 쿼리를 전송하고 나는 모든 하나 개의 쿼리에서이 작업을 수행 할 수있는 방법을 검색하고, 작동하지만EF 4.1 코드 우선 : 포함 및/또는 선택 방법을 사용할 때 탐색 속성을 주문하는 방법?

 var model = DbContext.SitePages 
      .Where(p => p.ParentId == null && p.Level == 1) 
      .OrderBy(p => p.Order) // ordering parent 
      .ToList(); 
     foreach (var child in model) { // loading children 
      DbContext.Entry(child) 
       .Collection(t => t.Children) 
       .Query() 
       .OrderBy(t => t.Order) // ordering children 
       .Load(); 
      foreach (var grand in child.Children) { // loading grandchildren 
       DbContext.Entry(grand) 
       .Collection(t => t.Children) 
       .Query() 
       .OrderBy(t => t.Order) // ordering grandchildren 
       .Load(); 
      } 
     } 

: 내 첫 번째 코드는이이었다. (예 : 첫 번째 코드 위와 같이) 이제

 var model2 = DbContext.SitePages 
      .Where(p => p.ParentId == null && p.Level == 1) 
      .OrderBy(p => p.Order) 
      .Include(p => p.Children // Children: how to order theme??? 
       .Select(c => c.Children) // Grandchildren: how to order them??? 
      ).ToList(); 

, 어떻게 주문할 수 있습니다 어린이들 (손자) 그들에게 선택 : @Slauma의 지침으로 나는이 하나에 쿼리를 변경 (위의 링크에 설명)?

+1

이 질문을보십시오. http://stackoverflow.com/questions/4156949/ef4-linq-ordering-parent-and-all-child-collections-with-eager-loading-include. 당신이하려고하는 것은 "eager loading"이라고 불리고, 분명히 당신은'OrderBy'를'Include'와 함께 사용할 수 없습니다. – devuxer

+0

예, 열심히로드하는 방법에 대해 알고 있습니다. (내 자신이 만든) 첫 번째 코드를 보면 각 수준의 각 개체에 foreach 문을 사용하는 것을 볼 수 있습니다 (자식에 대해서는 맨, 손자에게는 자식). 당신의 준비된 링크에 대해 설명했다. 그러나 이것은 데이터베이스에 대해 더 많은 쿼리를 필요로합니다! 나는 하나의 쿼리에서이 모든 것을 수행하는 방법을 찾고있다. –

+0

전체 구조를 열망 할 수 있습니까? 그런 다음 필요할 때 뷰에서 순서를 지정할 수 있습니까? 데이터 액세스 논리에서 프리젠 테이션 논리 (순서 지정)를 누출해야하는 이유는 거의 없습니다. –

답변

22

불행하게도 열망로드 (Include)는 어떤 필터링을 지원하거나로드의 정렬되지 않습니다 자식 컬렉션입니다.

  • Explicite 정렬 로딩으로 데이터베이스를 여러 번 왕복 할 수 있습니다. 귀하의 질문에 대한 첫 번째 코드 스 니펫입니다. 다중 왕복은 반드시 나쁜 것은 아니며 IncludeIncludecan lead to huge multiplication of transfered data between database and client 중첩 된 것을 염두에 두십시오.

  • 들이로드 된 후 메모리에 Include 또는 Include(....Select(....)) 및 정렬하려면 데이터

    사용 열망로드

  • :

    var model2 = DbContext.SitePages 
        .Where(p => p.ParentId == null && p.Level == 1) 
        .OrderBy(p => p.Order) 
        .Include(p => p.Children.Select(c => c.Children)) 
        .ToList(); 
    
    foreach (var parent in model2) 
    { 
        parent.Children = parent.Children.OrderBy(c => c.Order).ToList(); 
        foreach (var child in parent.Children) 
         child.Children = child.Children.OrderBy(cc => cc.Order).ToList(); 
    } 
    
  • 는 프로젝션을 사용

    var model2 = DbContext.SitePages 
        .Where(p => p.ParentId == null && p.Level == 1) 
        .OrderBy(p => p.Order) 
        .Select(p => new 
        { 
         Parent = p, 
         Children = p.Children.OrderBy(c => c.Order) 
          .Select(c => new 
          { 
           Child = c, 
           Children = c.Children.OrderBy(cc => cc.Order) 
          }) 
        }) 
        .ToList() // don't remove that! 
        .Select(a => a.Parent) 
        .ToList(); 
    

이 단 하나입니다 왕복 및 변경 추적을 사용하지 않으면 작동합니다 (이 쿼리에서는 .AsNoTracking()을 사용하지 마십시오). 이 투영의 모든 객체를 컨텍스트에로드해야합니다 (첫 번째 ToList()이 필요한 이유). 컨텍스트가 탐색 속성을 올바르게 함께 연결합니다 ("관계 범위").

+0

OMG 특별 감사 Slauma! 좋은 일을 잘 : D : D : D 그 작품, 나는 그것을 추적하고 오직 하나의 쿼리 db (^_^)에 대한 보냈다 친애하는 감사. 방금'.Select (c => new { 부모 = c, 어린이 = c.Children. OrderBy (cc => cc.Order) }})로 내부 '선택'을 변경했습니다. 다시 한번 고마워요. –

+1

@ChrisMoschini :'ProxyCreationEnabled'가 중요할까요? 나는 거의 변경 추적 프록시를 사용하지 않으며 관계 스팬은 여전히 ​​작동합니다. – Slauma

+0

@Slauma 네가 맞아! 이러한 종류의 투영을 수행하지 못하는 프록시를 사용하지 않고 빠른 읽기 전용 쿼리를 추적하지 않는 코드가 있습니다. 하지만 Proxy가 비활성화 된 것은 괜찮습니다. 렌치를 던지는 것은 AsNoTracking()입니다. –

0

다음을 시도해 보셨습니까?

... 선택 (c.children의 채널에서 ORDERBY의 ch.property desending 선택 채널) ...

+0

작동하지 않습니다! 오류는 * 포함 경로 식은 해당 유형에 정의 된 탐색 속성을 참조해야합니다. 참조 탐색 속성 및 콜렉션 탐색 속성의 선택 연산자에 점선으로 된 경로를 사용하십시오. 매개 변수 이름 : 경로 * –

관련 문제