在LINQ中實踐多條件LEFT JOIN

同事今天問了一個LINQ下使用多條件比對產生LEFT JOIN的問題,讓我也學到了新東西,特地PO文備忘。

這回不寫程式,直接用威到不行的LINQPad做示範。

假想的題目是有個員工資料表Employee,Primary Key是DeptId及UserId,除了UserName,另有SubstituteDeptId及SubstituteUserId指向該員工的代理人。公司共有三人,工程部的Jeffrey及Darkthread互為代理人,業務部的Mouth Cannon先生因火力強大,無人能代理,故代理人從缺。我們希望產生一個清單,列出部門、員編、姓名及代理人姓名,由於有人無代理人,故需要用LEFT JOIN處理。

依據MSDN文件的介紹,LINQ要產生LEFT JOIN的關鍵在於先將JOIN結果形成群組,再借重DefaultIfEmpty()方法容忍比對不符時的狀況,一般是傳回屬性值為null的空物件。

在此案例中還有一個特別之處,是必須同時比對DeptId及UserId兩個欄位做JOIN(不要問我為什麼不讓UserId唯一就好? 不這樣假設要怎麼示範多條件?),由於join ... on時只接受單一equals關鍵字作比對,因此當有多條件時,要將多欄位各自組一個匿名類別(如: new { s.DeptId, s.UserId }),再用equals比對匿名類別。但由於是同一資料表自己JOIN自己,JOIN時比對欄位名稱不相同,名因此要重新命名匿名類別的屬性名稱(如: new { DeptId = e.SubstituteDeptId, UserId = e.SubstituteUserId }),否則會產生The type of one of the expressions in the join clause is incorrect.  Type inference failed in the call to 'GroupJoin'.錯誤!

完整的LINQ語法如下:

排版顯示純文字
from e in Employees
join s in Employees
on new { DeptId = e.SubstituteDeptId, 
         UserId = e.SubstituteUserId } equals 
   new { s.DeptId, s.UserId } into subGrp
from s in subGrp.DefaultIfEmpty()
select new 
{
    e.DeptId, e.UserId, e.UserName,
    Substitute = s.UserName ?? "NA"
}

大功告成!

原文地址:https://www.cnblogs.com/dudu837/p/1870648.html