许飞

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

用 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,簡單的關聯

image

裡面建的假資料,我故意把某一個類別(筆電)做成沒有關聯資料。

image

接著開始用拉一個Linq to SQL,然後寫Code

image

我個人覺得SelectMany非常好用,因為可再傳入一個資料集,並且可利用原資料集對第二個資料集做篩選。

寫完之後,利用SQL Server Profiler來看看他組出什麼樣的T-SQL語法

image

看起來非常好,就是我要的。再隨便補上一點Code,看實際撈出資料的結果

01 public ActionResult Index()
02 {
03     MyDataContext db = new MyDataContext();
04  
05     var 類別=db.類別;
06  
07     var 產品資訊 = 類別.SelectMany(p => p.產品.DefaultIfEmpty()
08                            , (c, d) => new { 類別名稱=c.名稱,產品名稱=d.產品名稱});
09  
10  
11     StringBuilder sb = new StringBuilder();
12  
13     sb.Append("<table style='border:1px solid red'>");
14  
15     foreach(var p in 產品資訊.OrderBy(p=>p.類別名稱)){
16         sb.Append("<tr><td>" + p.類別名稱 + "</td><td>" + p.產品名稱 + "</td></tr>");
17     }
18     sb.Append("</table>");
19  
20     return Content(sb.ToString());
21 }

image

這樣就完成啦。

補充一下:

要是沒有加DefaultIfEmpty()的話

1 var 產品資訊 = 類別.SelectMany(p => p.產品
2                               , (c, d) => new { 類別名稱=c.名稱,產品名稱=d.產品名稱});

,產出來的T-SQL語法就變成下面這樣

image

結果當然就是,沒有的那個類別不會出現了。

image

posted on 2012-09-14 10:11  许飞  阅读(210)  评论(0)    收藏  举报