使用 LINQ 執行 Join 時,多條件中有Nullable<T>的處理方式

  • 7045
  • 0
  • C#
  • 2012-04-27

前一篇文章 在 LINQ 裡使用 Left Join 還有哪些需要注意的呢? 中,筆者概括的介紹了在 LINQ 中,使用 LEFT JOIN 與多條件的使用方式,以及需要注意的地方。今天筆者在撰寫程式時又發現一個有趣的地方,就是當使用EDM時,多條件的 JOIN 當中,如果條件有些是 Nullable,也就是在資料庫中是可允許 null 的欄位該怎麼辦呢?

前一篇文章 在 LINQ 裡使用 Left Join 還有哪些需要注意的呢? 中,筆者概括的介紹了在 LINQ 中,使用 LEFT JOIN 與多條件的使用方式,以及需要注意的地方。今天筆者在撰寫程式時又發現一個有趣的地方,就是當使用EDM時,多條件的 JOIN 當中,如果條件有些是 Nullable<T>,也就是在資料庫中是可允許 null 的欄位該怎麼辦呢?這時你應該會得到像下面這樣的錯誤:

image

有時我們會很直覺的將程式改為如下:

   1:  from tran in m.DefaultIfEmpty() where tran!=null join item in VirusChange_RGHeight_Items
   2:      on new {RGHeightID=tran.RGHeightID.HasValue?tran.RGHeightID.Value:0, Pathogen_ID=tran.Pathogen_ID.HasValue?tran.Pathogen_ID.Value:0} equals new {item.Parent_ID, item.Pathogen_ID} into mm 

 

又或者式改為如下:

   1:  from tran in m.DefaultIfEmpty() where tran!=null join item in VirusChange_RGHeight_Items
   2:      on new {tran.RGHeightID,tran.Pathogen_ID} equals new {RGHeightID=item.Parent_ID.GetValueOrDefault(0), Pathogen_ID=item.Pathogen_ID.GetValueOrDefault(0)} into mm 

 

不過,很遺憾的,還是不行……

其時一樣回歸到 C# 的 CLR 平台上對於型別的要求是非常嚴謹的,雖然 LINQ 在這裡有自動型別推斷的機制,你想想看,int? 與 int 直接比較是非常不嚴警的做法。因此到最後可以可以用的版本是如下:

   1:  from tran in m.DefaultIfEmpty() where tran!=null join item in VirusChange_RGHeight_Items
   2:      on new {tran.RGHeightID,tran.Pathogen_ID} equals new {RGHeightID=(int?)item.Parent_ID, Pathogen_ID=(int?)item.Pathogen_ID} into mm 

 

如同在 LINQ 的 Where 條件式裡使用 ToString() 一樣,在 LINQ to Entities 裡面它必須對應到一個 .NET 的CLR 的一個實體,必須經由這個實體轉換為 SQL 語句,而且在 LINQ to Entities 中的查詢條件是使用 IQueryable<T>,而在裡面下的標準函式會轉譯成所使用之 (提供者資料庫) 的正確對應存放函式。 這樣就可以真的達到跨資料來源的型式。簡單的說,就是它必須是可以直接被轉換為目的資料庫的 SQL 語句的。可是呢!為了在不同的資料庫、來源,提供一致的查詢方式。因此在 LINQ to Entities 裡面如果使用了一些無法明確對映到基礎資料來源的 CLR 方法,就會得到一個 NotSupportedException 的例外。 

 

結語:

 

剛開始或許會覺得奇怪,想不明白,其實這是因為在 LINQ to Entities 這裡較 LINQ to SQL 來的嚴謹。它未來會支援多種類的資料庫。我想在這個部份也不能這麼鬆散。

 

參考資料:

CLR Method to Canonical Function Mapping

http://msdn.microsoft.com/en-us/library/bb738681.aspx

Workarounds for using custom methods/extension methods in LINQ to Entities

http://stackoverflow.com/questions/4867100/workarounds-for-using-custom-methods-extension-methods-in-linq-to-entities

標準函式 (Entity SQL)

http://msdn.microsoft.com/zh-tw/library/bb738626.aspx

MSDN 論壇 (LINQ to Entities does not recognize the method 'System.String ToString()' method)

http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/19a33909-c532-419b-a533-57e431c0b30b

LINQ to Entities 中的已知問題和考量因素

http://msdn.microsoft.com/zh-tw/library/bb896317.aspx#TypeConversionErrors


 

簽名:

學習是一趟奇妙的旅程

這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。

軟體開發之路(FB 社團)https://www.facebook.com/groups/361804473860062/

Gelis 程式設計訓練營(粉絲團)https://www.facebook.com/gelis.dev.learning/


 

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

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