2012-03-15 24 views
62

Tôi đang cố gắng thực hiện một Tham gia giữa nhiều bảng trong LINQ. Tôi có các lớp sau:Cách thực hiện Tham gia giữa nhiều bảng trong LINQ lambda

Product {Id, ProdName, ProdQty} 

Category {Id, CatName} 

ProductCategory{ProdId, CatId} //association table 

Và tôi sử dụng đoạn mã sau (nơi product, categoryproductcategory là trường hợp của các lớp trên):

var query = product.Join(productcategory, p => p.Id, pc => pc.ProdID, (p, pc) => new {product = p, productcategory = pc}) 
        .Join(category, ppc => ppc.productcategory.CatId, c => c.Id, (ppc, c) => new { productproductcategory = ppc, category = c}); 

Với mã này, tôi có được một đối tượng từ sau lớp học:

QueryClass { productproductcategory, category} 

Trường hợp producproductcategory thuộc loại:

ProductProductCategoryClass {product, productcategory} 

Tôi không hiểu nơi "bảng" đã tham gia là, tôi đã mong đợi một lớp một lớp chứa tất cả các thuộc tính từ các lớp liên quan.

Mục đích của tôi là để cư một đối tượng với một số tính chất phát sinh từ việc truy vấn:

CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments }); 

làm thế nào tôi có thể đạt được mục tiêu này?

+0

Tôi không hiểu ... tại sao ** m.ProdId = ??? ** thay vì ** prodId = m.ProdId **? –

+0

Vì tôi không biết trước cách điều hướng và nhận ProdId – CiccioMiami

Trả lời

124

Đối với tham gia, tôi rất thích truy vấn-cú pháp cho tất cả các chi tiết được hạnh phúc ẩn (không phải là ít trong số đó là minh bạch số nhận dạng liên quan đến các phép chiếu trung gian dọc theo cách hiển thị trong tương đương dấu chấm-cú pháp). Tuy nhiên, bạn hỏi về Lambdas mà tôi nghĩ bạn có mọi thứ bạn cần - bạn chỉ cần đặt tất cả lại với nhau.

var categorizedProducts = product 
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc }) 
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ppc, c }) 
    .Select(m => new { 
     ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId 
     CatId = m.c.CatId 
     // other assignments 
    }); 

Nếu cần, bạn có thể lưu tham gia vào biến cục bộ và sử dụng lại sau, tuy nhiên thiếu các chi tiết khác ngược lại, tôi không thấy lý do nào để giới thiệu biến cục bộ.

Ngoài ra, bạn có thể ném Select vào lambda cuối cùng của thứ hai Join (một lần nữa, với điều kiện không có các hoạt động khác mà phụ thuộc vào sự tham gia kết quả) mà sẽ cung cấp cho:

var categorizedProducts = product 
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc }) 
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { 
     ProdId = ppc.p.Id, // or ppc.pc.ProdId 
     CatId = c.CatId 
     // other assignments 
    }); 

... và thực hiện nỗ lực cuối cùng để bán cho bạn về cú pháp truy vấn, điều này sẽ trông giống như sau:

var categorizedProducts = 
    from p in product 
    join pc in productcategory on p.Id equals pc.ProdId 
    join c in category on pc.CatId equals c.Id 
    select new { 
     ProdId = p.Id, // or pc.ProdId 
     CatId = c.CatId 
     // other assignments 
    }; 

Bàn tay của bạn có thể bị ràng buộc khi có sẵn cú pháp truy vấn. Tôi biết một số cửa hàng có nhiệm vụ như vậy - thường dựa trên khái niệm rằng cú pháp truy vấn có phần hạn chế hơn so với cú pháp chấm. Có nhiều lý do khác, như "tại sao tôi nên tìm hiểu cú pháp thứ hai nếu tôi có thể làm mọi thứ và nhiều hơn nữa trong cú pháp chấm?"Như phần cuối này cho thấy - có những chi tiết mà cú pháp truy vấn ẩn có thể làm cho nó có giá trị với việc cải thiện khả năng đọc nó mang lại: tất cả những dự đoán và số nhận dạng trung gian mà bạn phải nấu đều vui vẻ không phải ở phía trước và giữa -stage trong phiên bản truy vấn-cú pháp - họ là nền khuẩn Tắt xà phòng hộp của tôi bây giờ -.. dù sao đi nữa, cảm ơn cho câu hỏi :)

+3

Cảm ơn giải pháp của bạn là hoàn chỉnh hơn. Tôi đồng ý cú pháp truy vấn trong một số trường hợp rõ ràng hơn nhưng bạn đã đoán đúng, tôi đã được yêu cầu sử dụng lambda. Hơn nữa tôi phải thực hiện điều này tham gia hơn 6 bảng, và ký hiệu chấm trong trường hợp này là gọn gàng hơn – CiccioMiami

+0

+1 Hoàn hảo ... !!! –

+0

@devgeezer Nếu chúng ta cần điều kiện bổ sung trong câu lệnh 'JOIN' thì sao? làm sao chúng ta làm việc đó bây giờ? Ví dụ, trong 'join pc trong productcategory trên p.Id bằng dòng pc.ProdId', chúng ta cần thêm' và p.Id == 1'. –

9

gì bạn đã nhìn thấy là những gì bạn nhận được - và đó là chính xác những gì bạn yêu cầu, ở đây:

(ppc, c) => new { productproductcategory = ppc, category = c} 

Đó là một biểu thức lambda trở về một loại vô danh với hai thuộc tính.

Trong CategorizedProducts của bạn, bạn chỉ cần đi qua những thuộc tính:

CategorizedProducts catProducts = query.Select(
     m => new { 
      ProdId = m.productproductcategory.product.Id, 
      CatId = m.category.CatId, 
      // other assignments 
      }); 
+0

Cảm ơn bạn. Tôi hiểu cuộc thảo luận về lớp ẩn danh nhưng các thuộc tính của nó chỉ chứa các đối tượng lớp đáp ứng truy vấn? Và điều gì sẽ xảy ra sau khi tôi thực hiện 2 lần tham gia? productproductcategory.product không được nối với danh mục phải không? – CiccioMiami

+0

@CiccioMiami: Vâng, các thuộc tính là * tham chiếu * đối tượng, vâng. Nó không thực sự rõ ràng những gì bạn có nghĩa là "không tham gia" - những thông tin nào bạn không nhận được từ truy vấn của bạn mà bạn muốn nhận được? –

+0

Với lần tham gia đầu tiên, tôi nhận được sự tham gia giữa các sản phẩm và danh mục sản phẩm. Với lần thứ hai, tôi nhận được sự kết hợp giữa productcategory (sản phẩm gia nhập) và thể loại. Điều đó có nghĩa là thông tin về phép nối nhiều chỉ được chứa trong productproductcategory. Điều này có nghĩa là sản phẩm (và danh mục) chỉ được kết hợp với productcategory. – CiccioMiami

3

mất nhìn vào mẫu mã này từ dự án của tôi

public static IList<Letter> GetDepartmentLettersLinq(int departmentId) 
{ 
    IEnumerable<Letter> allDepartmentLetters = 
     from allLetter in LetterService.GetAllLetters() 
     join allUser in UserService.GetAllUsers() on allLetter.EmployeeID equals allUser.ID into usersGroup 
     from user in usersGroup.DefaultIfEmpty()// here is the tricky part 
     join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID 
     where allDepartment.ID == departmentId 
     select allLetter; 

    return allDepartmentLetters.ToArray(); 
} 

trong mã này tôi đã tham gia 3 bảng và tôi đã tham gia điều kiện tham gia từ điều khoản

lưu ý: các lớp Dịch vụ chỉ bị biến dạng (encapsu) trễ) các hoạt động cơ sở dữ liệu

1
public ActionResult Index() 
    { 
     List<CustomerOrder_Result> obj = new List<CustomerOrder_Result>(); 

     var orderlist = (from a in db.OrderMasters 
         join b in db.Customers on a.CustomerId equals b.Id 
         join c in db.CustomerAddresses on b.Id equals c.CustomerId 
         where a.Status == "Pending" 
         select new 
         { 
          Customername = b.Customername, 
          Phone = b.Phone, 
          OrderId = a.OrderId, 
          OrderDate = a.OrderDate, 
          NoOfItems = a.NoOfItems, 
          Order_amt = a.Order_amt, 
          dis_amt = a.Dis_amt, 
          net_amt = a.Net_amt, 
          status=a.Status, 
          address = c.address, 
          City = c.City, 
          State = c.State, 
          Pin = c.Pin 

         }) ; 
     foreach (var item in orderlist) 
     { 

      CustomerOrder_Result clr = new CustomerOrder_Result(); 
      clr.Customername=item.Customername; 
      clr.Phone = item.Phone; 
      clr.OrderId = item.OrderId; 
      clr.OrderDate = item.OrderDate; 
      clr.NoOfItems = item.NoOfItems; 
      clr.Order_amt = item.Order_amt; 
      clr.net_amt = item.net_amt; 
      clr.address = item.address; 
      clr.City = item.City; 
      clr.State = item.State; 
      clr.Pin = item.Pin; 
      clr.status = item.status; 

      obj.Add(clr); 



     } 
+1

Mặc dù đoạn mã này có thể giải quyết được câu hỏi, [bao gồm cả giải thích] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) thực sự giúp cải thiện chất lượng bài đăng của bạn.Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. –

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