在 .NET 3.5 出來至今,都已經3-4年的光景了,相信現在已經有許多專案接導入了LINQ,在專案中使用LINQ,對資料庫的存取來說這表示您可能是使用 Microsoft Entity Framework (EDM) 或LINQ to SQL 等。我們都知道在LINQ裡如何使用 Join,但如果是 Left Join
在 .NET 3.5 出來至今,都已經3-4年的光景了,相信現在已經有許多專案接導入了LINQ,在專案中使用LINQ,對資料庫的存取來說這表示您可能是使用 Microsoft Entity Framework (EDM) 或LINQ to SQL 等。我們都知道在LINQ裡如何使用 Join,但如果是 Left Join,由於LINQ的join 本來就不像是真正的 SQL 單純的對資料庫進行聯集,在程式語言物件化的世界裡,透過Class之間相互關聯參考,有時對應不到的如果是 null reference 參考類型的物件,需要做特別的一些處理才可以達到相同的效果。
如下面範例資料表 Account (帳號主檔)、RoleMain (角色主檔)、UserRole (帳號角色關聯檔) 三個範例資料表中,由於在RoleMain中定義的 [一般使用者]在Account中並沒有資料,所以可以來模擬 Left Join的狀況。如下圖,在SQL Server Management Studio 中的SQL 查詢:
換成 LINQ 的寫法變成如下:
其中欄位 UR_SystemID, UA_LoginID, UA_UserName 與 SQL Server Management Studio 中的一樣都是 null 值。
需要注意的地方是:
1. 在 join 的條件中如果有多個,才需要再放入一個暱名型別中,如:on new {r.RM_RoleId, r.RM_RoleName} equals new {u.UR_RMRoleID, u.UR_RMRoleName} into grp1
2. 在輸出的型態中,如果可能是 null 的是 Real Type 如:(int, DateTime 等),在物件化的世界裡,你就需要轉換成對等的輸出 (int? , DateTime?) 等。如上的範例,因為 UR_SystemID 為 int,所以當我判定當時的值為 null 時,我就 new 一個 Nullable<int>() 輸出來填補。您如果不這樣做的話,會得到一個 Int32 型別轉換失敗的錯誤
而匿名型別也不允許你直接給 null 輸出,如果你直接輸出 null ,會引發另一個錯誤,如下圖:
另外一個比較有趣的,我們時常在SQL裡常用的 Sub Query,在LINQ裡直接寫在匿名屬性的輸出的後面即可。如下,利用當時的 SystemID 找出 SystemName 的寫法如下:
如何!是不是很簡單呢?
結論:
使用 LINQ 你不能以寫一般 SQL 的角度來思考。您必須以物件化語言的角度來思考,而這裡的物件化語言是C#。
參考資料:
GroupJoin 方法
http://msdn.microsoft.com/zh-tw/library/dd383965.aspx
join clause (C# Reference)
http://msdn.microsoft.com/en-us/library/bb311040.aspx
簽名:
學習是一趟奇妙的旅程
這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。
軟體開發之路(FB 社團):https://www.facebook.com/groups/361804473860062/
Gelis 程式設計訓練營(粉絲團):https://www.facebook.com/gelis.dev.learning/
如果文章對您有用,幫我點一下讚,或是點一下『我要推薦』,這會讓我更有動力的為各位讀者撰寫下一篇文章。
非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^