7

Đây là bước thứ hai của câu hỏi được giải thích here (EF 4.1 code-first: How to load related data (parent-child-grandchild)?). Theo hướng dẫn của @Slauma tôi có thể truy xuất dữ liệu. Mã đầu tiên của tôi là:EF 4.1 mã đầu tiên: Cách đặt hàng thuộc tính điều hướng khi sử dụng Bao gồm và/hoặc Chọn phương pháp?

 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(); 
      } 
     } 

Nó hoạt động, nhưng điều này sẽ gửi nhiều truy vấn đến cơ sở dữ liệu và tôi đang tìm cách thực hiện tất cả trong một truy vấn. Bằng cách hướng dẫn @Slauma 's (giải thích trên diễn đàn) tôi thay đổi truy vấn để này:

 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(); 

Bây giờ, làm thế nào tôi có thể đặt trẻ em (cháu) khi chọn chúng (chẳng hạn như mã đầu tiên ở trên)?

+1

Hãy xem câu hỏi này: http://stackoverflow.com/questions/4156949/ef4-linq-ordering-parent-and-all-child-collections-with-eager-loading-include. Những gì bạn đang cố gắng làm được gọi là "háo hức tải", và rõ ràng, bạn không thể sử dụng 'OrderBy' với' Bao gồm'. – devuxer

+0

Có, tôi biết về tải háo hức, và nếu bạn nhìn vào mã đầu tiên (được tạo bởi chính tôi) bạn sẽ thấy tôi sử dụng một tuyên bố foreach trên mỗi đối tượng ở mỗi cấp độ (đầu cho trẻ em, và, con cho cháu) như những gì được giải thích trên liên kết chuẩn bị của bạn. nhưng điều này cần thêm truy vấn đối với cơ sở dữ liệu! Tôi đang tìm kiếm một cách để làm điều này tất cả trong một truy vấn, không nhiều hơn nữa! –

+0

Bạn có thể mong muốn tải toàn bộ cấu trúc của bạn, sau đó đặt hàng trong quan điểm của bạn khi họ được yêu cầu? Có hầu như không có lý do tại sao bạn nên bị rò rỉ logic trình bày (đặt hàng) trong logic truy cập dữ liệu của bạn. –

Trả lời

22

tải Thật không may háo hức (Include) không hỗ trợ bất kỳ lọc hoặc sắp xếp của tải bộ sưu tập con. Có ba tùy chọn để đạt được những gì bạn muốn:

  • Nhiều vòng lặp tới cơ sở dữ liệu với tải được sắp xếp explicite. Đó là đoạn mã đầu tiên trong câu hỏi của bạn. Xin lưu ý rằng nhiều chuyến đi khứ hồi không nhất thiết phải là xấu và rằng Include và lồng nhau Includecan lead to huge multiplication of transfered data between database and client.

  • Sử dụng tải háo hức với Include hoặc Include(....Select(....)) và sắp xếp dữ liệu trong bộ nhớ sau khi được nạp:

    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(); 
    } 
    
  • Dùng chiếu:

    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(); 
    

này chỉ là một đơn roundtrip và hoạt động nếu bạn không tắt theo dõi thay đổi (không sử dụng .AsNoTracking() trong truy vấn này). Tất cả các đối tượng trong phép chiếu này phải được tải vào ngữ cảnh (lý do tại sao ToList() đầu tiên cần thiết) và ngữ cảnh sẽ buộc các thuộc tính điều hướng chính xác với nhau (đó là một tính năng được gọi là "Khoảng mối quan hệ").

+0

Cảm ơn đặc biệt OMG Slauma! Tốt làm tốt công việc: D: D: D Đó là công trình, tôi theo dõi nó và JUST ONE truy vấn gửi chống lại db (^_^) đặc biệt cảm ơn thân yêu. Tôi chỉ thay đổi bên trong 'Chọn' bằng' .Select (c => new { Parent = c, Children = c.Children. OrderBy (cc => cc.Order) }) '. Cảm ơn một lần nữa và một lần nữa. –

+1

@ChrisMoschini: Bạn có chắc chắn rằng các vấn đề 'ProxyCreationEnabled' không? Tôi gần như không bao giờ sử dụng thay đổi theo dõi proxy và khoảng thời gian mối quan hệ vẫn hoạt động. – Slauma

+0

@Slauma Bạn nói đúng! Chúng tôi có mã sử dụng cả Proxy bị vô hiệu hóa và không theo dõi các truy vấn chỉ đọc nhanh mà không thực hiện loại chiếu này; nhưng Proxy vô hiệu hóa chỉ là tốt, nó chỉ là AsNoTracking() mà ném một cờ lê. –

0

Bạn đã thử theo dõi chưa?

... Chọn (từ ch trong c.children orderby ch.property desending chọn ch) ...

+0

Không hoạt động! Lỗi là * Biểu thức đường dẫn Bao gồm phải tham chiếu đến thuộc tính điều hướng được xác định trên loại. Sử dụng đường dẫn rải rác cho thuộc tính điều hướng tham chiếu và toán tử Chọn cho thuộc tính điều hướng bộ sưu tập. Tên thông số: đường dẫn * –

Các vấn đề liên quan