用 Linq to SQL 完成Left join-DefaultIfEmpty
一個資料庫要是正規化做得好,往往查一個資料都要join來join去的。
這幾個月因為都一直在用Linq to SQL,因此很多繁複的T-SQL指令都比較少在用了
只要關聯有拉好,用點的就可以點到關聯的table,省去很多麻煩。
但最近為了一個以前輕鬆可以做到的left join可是燒了一下頭。
因為用點的,只點的到有相關聯的資料,要是子table裡沒有父table的某筆PK
那該筆父table的資料就會撈不到。
上網查了一下,查到有個方法可以解決這個問題 Enumerable.DefaultIfEmpty 方法
不過大部分的寫法 都是用Linq Expression方式寫的(範例LEFT JOINS and DefaultIfEmpty Operator in LINQ)。
但我比較習慣用lambda寫法,所以就紀錄一下改寫成lambda的樣子
首先先來看table,簡單的關聯
裡面建的假資料,我故意把某一個類別(筆電)做成沒有關聯資料。
接著開始用拉一個Linq to SQL,然後寫Code
我個人覺得SelectMany非常好用,因為可再傳入一個資料集,並且可利用原資料集對第二個資料集做篩選。
寫完之後,利用SQL Server Profiler來看看他組出什麼樣的T-SQL語法
看起來非常好,就是我要的。再隨便補上一點Code,看實際撈出資料的結果
public ActionResult Index()
{
MyDataContext db = new MyDataContext();
var 類別=db.類別;
var 產品資訊 = 類別.SelectMany(p => p.產品.DefaultIfEmpty()
, (c, d) => new { 類別名稱=c.名稱,產品名稱=d.產品名稱});
StringBuilder sb = new StringBuilder();
sb.Append("<table style='border:1px solid red'>");
foreach(var p in 產品資訊.OrderBy(p=>p.類別名稱)){
sb.Append("<tr><td>" + p.類別名稱 + "</td><td>" + p.產品名稱 + "</td></tr>");
}
sb.Append("</table>");
return Content(sb.ToString());
}
這樣就完成啦。
補充一下:
要是沒有加DefaultIfEmpty()的話
var 產品資訊 = 類別.SelectMany(p => p.產品
, (c, d) => new { 類別名稱=c.名稱,產品名稱=d.產品名稱});
,產出來的T-SQL語法就變成下面這樣
結果當然就是,沒有的那個類別不會出現了。