2010-07-28 48 views
131

Đây có thể là một câu hỏi thực sự nhưng cách tốt nhất để bao gồm nhiều thực thể con khi viết truy vấn kéo dài BA cấp (hoặc nhiều hơn)?Entity framework linq query Bao gồm() nhiều thực thể con

ví dụ: Tôi có 4 bảng: Company, Employee, Employee_CarEmployee_Country

Công ty có tỷ lệ 1: mối quan hệ m với nhân viên.

Nhân viên có mối quan hệ 1: m với cả Employee_Car và Employee_Country.

Nếu tôi muốn viết một truy vấn mà trả về dữ liệu từ tất cả 4 bảng, Tôi hiện đang viết:

Company company = context.Companies 
         .Include("Employee.Employee_Car") 
         .Include("Employee.Employee_Country") 
         .FirstOrDefault(c => c.Id == companyID); 

Cần phải có một cách thanh lịch hơn! Đây là dài hơi và tạo ra SQL khủng khiếp

Tôi đang sử dụng EF4 với VS 2010

Trả lời

163

Sử dụng extension methods. Thay thế NameOfContext bằng tên của ngữ cảnh đối tượng của bạn.

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

} 

Sau đó, mã của bạn trở nên

 Company company = 
      context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID); 

    //or if you want even more 
    Company company = 
      context.CompanyById(companyID); 
+5

điều này thật tuyệt vời. –

+0

Nhưng tôi muốn sử dụng nó như này: '// bên Extensions lớp public static public static IQueryable CompleteCompanies (DbSet bảng này) { trở lại bảng .Include ("Employee.Employee_Car") .Include (" Employee.Employee_Country "); } // mã sẽ là ... Công ty công ty = context.Companies.CompleteCompanies(). FirstOrDefault (c => c.Id == companyID); // tương tự cho phương pháp nâng cao tiếp theo' – Hamid

+0

Bullsye Nix. Tiện ích mở rộng phải là cổng gọi đầu tiên cho ... cũng ... mở rộng chức năng được xác định trước. – ComeIn

24

Bạn có thể tìm thấy bài viết này quan tâm trong đó có sẵn tại codeplex.com.

Bài viết trình bày một cách mới để thể hiện các truy vấn trải dài trên nhiều bảng dưới dạng biểu đồ đồ thị khai báo.

Hơn nữa, bài viết có so sánh hiệu suất toàn diện về phương pháp mới này với các truy vấn EF. Phân tích này cho thấy GBQ nhanh hơn nhanh hơn các truy vấn EF.

+1

Bài viết rất thú vị! –

91

EF 4.1 để EF 6

Có một strongly typed .Include cho phép độ sâu yêu cầu xếp hàng háo hức để được xác định bằng cách cung cấp Chọn biểu đến độ sâu thích hợp:

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 được tạo ra trong cả hai trường hợp vẫn không có nghĩa trực quan, nhưng có vẻ đủ trình diễn.Tôi đã đặt một ví dụ nhỏ về GitHub here

EF Lõi

EF Core có một phương pháp mở rộng mới, .ThenInclude(), mặc dù cú pháp là slightly different:

var company = context.Companies 
        .Include(co => co.Employees) 
          .ThenInclude(emp => emp.Employee_Car) 
         ... 

Theo các tài liệu, tôi sẽ giữ thêm 'thụt lề' trong số .ThenInclude để bảo vệ sự tỉnh táo của bạn.

Obsolete Thông tin (Đừng làm điều này):

Bội cháu tải thể được thực hiện trong một bước, nhưng điều này đòi hỏi một sự đảo ngược khá vụng về sao lưu biểu đồ trước khi đi xuống nút tiếp theo (NB: Đây kHÔNG làm việc với AsNoTracking() - bạn sẽ nhận được một lỗi runtime):

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

Vì vậy, tôi sẽ ở lại với các tùy chọn đầu tiên (một Bao gồm mỗi lá mô hình sâu tổ chức).

+3

Tôi đã tự hỏi làm thế nào để làm điều đó với đánh máy mạnh mẽ. Chiếu trẻ em bằng Chọn là câu trả lời! –

+6

Cảm ơn bạn đã thêm không gian tên !!! – GRGodoi

+1

Phương trình "co.Employees.Select (...)" của tôi hiển thị lỗi cú pháp trên "Chọn", nói rằng "Nhân viên" không chứa định nghĩa cho 'Chọn' [hoặc phương pháp mở rộng] ". Tôi đã bao gồm System.Data.Entity. Tôi chỉ muốn lấy một cột đơn từ bảng đã nối. –

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