在 LINQ 裡使用 Left Join 還有哪些需要注意的呢?

  • 11289
  • 0
  • C#
  • 2012-04-24

在 .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 查詢:

image

換成 LINQ 的寫法變成如下:

image

其中欄位 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 型別轉換失敗的錯誤

image

而匿名型別也不允許你直接給 null 輸出,如果你直接輸出 null ,會引發另一個錯誤,如下圖:

image

另外一個比較有趣的,我們時常在SQL裡常用的 Sub Query,在LINQ裡直接寫在匿名屬性的輸出的後面即可。如下,利用當時的 SystemID 找出 SystemName 的寫法如下:

image

如何!是不是很簡單呢?

 

結論:

使用 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/


 

如果文章對您有用,幫我點一下讚,或是點一下『我要推薦,這會讓我更有動力的為各位讀者撰寫下一篇文章。

非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^