2012-03-15 76 views
62

我試圖執行一個LINQ中的多個表之間的連接。我有以下類:如何執行LINQ lambda中的多個表之間的連接

Product {Id, ProdName, ProdQty} 

Category {Id, CatName} 

ProductCategory{ProdId, CatId} //association table 

我使用下面的代碼(其中productcategoryproductcategory是上述類的實例):

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

有了這個代碼我從獲得的對象下面的類:

QueryClass { productproductcategory, category} 

哪裏producproductcategory的類型爲:

ProductProductCategoryClass {product, productcategory} 

我不明白的地方的加盟「表」是,我期待包含從參與類所有屬性單一類

我的目的是來用查詢產生的一些屬性另一個對象:

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

我怎樣才能實現這一目標?

+0

我不明白...爲什麼** m.ProdId = ** **而不是** prodId = m.ProdId **? – 2012-03-15 13:03:12

+0

因爲我不知道如何導航和獲得產品 – CiccioMiami 2012-03-15 13:16:27

回答

124

對於加入,我強烈希望查詢的語法對於那些愉快地隱藏所有細節(而不是其中的是透明標識符與中間投影相關,這在點語法等價中是明顯的)。不過,你問Lambdas我認爲你有你需要的一切 - 你只需要把它放在一起。

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

如果需要,你可以保存加入到一個局部變量和以後重新使用它,但缺乏其他細節,相反,我認爲沒有理由引進的局部變量。

此外,您可以扔Select進入第二Join最後拉姆達(同樣,只要不依賴於連接結果等操作),這將使:

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

...和最後一次試圖向你推銷查詢語法,這看起來像這樣:

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

你的手可能是綁定在查詢語法是否可用。我知道一些商店有這樣的任務 - 通常基於這樣的概念,即查詢語法比點語法更有限。還有其他一些原因,比如「爲什麼我應該學習第二種語法,如果我可以在點語法中做更多的事情?「正如最後一部分所顯示的那樣 - 有些查詢語法隱藏的細節可以讓它值得接受,因爲它帶來了可讀性的提高:所有那些你必須做的中間預測和標識符都非常適合不在前端和中心-stage在查詢語法版本 - 他們是背景絨毛關我的香皂盒,現在 - 。無論如何,感謝您的問題:)

+3

謝謝你的解決方案更完整。我同意在某些情況下查詢語法更清晰,但你猜對了,我被要求使用lambda。此外,我必須使這個連接超過6桌,並在這種情況下,點符號更整齊 – CiccioMiami 2012-03-15 15:27:36

+0

+1完美... !!! – 2014-08-21 10:31:45

+0

@devgeezer如果我們需要'JOIN'語句中的附加條件呢?我們如何做到這一點?例如,在'pc.productcategory中加入pc到p.Id等於pc.ProdId'行,我們需要添加'和p.Id == 1'。 – 2016-09-27 02:30:33

9

你看到的就是你得到了什麼 - 這是你問什麼,可以在這裏:

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

這是一個lambda表達式返回一個匿名類型與這兩個屬性。

在你CategorizedProducts,你只需要通過這些屬性去:

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

謝謝。我理解關於匿名類的討論,但其屬性僅包含滿足查詢的類對象?我執行2連接後會發生什麼? productproductcategory.product沒有加入category right? – CiccioMiami 2012-03-15 13:15:47

+0

@CiccioMiami:嗯,屬性是*對象的引用,是的。 「未加入」的含義並不十分清楚 - 您希望從查詢中獲得哪些信息? – 2012-03-15 13:17:54

+0

第一次加入時,我獲得了產品和產品類別之間的連接。隨着第二我得到產品類別(加入產品)和類別之間的聯接。這意味着關於多重連接的信息只包含在productproductcategory中。這意味着產品(和類別)只與產品類別連接。 – CiccioMiami 2012-03-15 13:30:47

3

看一看這一示例代碼從我的項目

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

在這段代碼中,我加入了3個表格,並且從第

號 號 號

號開始連接條件注意:服務類只是被扭曲(encapsu後期)數據庫操作

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

雖然此代碼段可能會解決問題,但[包括解釋](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。 – 2017-03-29 12:38:02

相關問題