2012-08-22 21 views
0

我需要下面的代碼來處理任何IQueryable,即使底層存儲庫只是一個數組。這在我的單元測試中使用假存儲器陣列後備存儲器時會引發NRE。很明顯,因爲y可能爲空,特別是在左外連接後,y不能自行幫助,而是爲空。EF空組檢查按分組

var x = from y in SomeIQueryable 
     group y by y.someForeignKey 
     into z 
     select z; 

我已將它更改爲以下內容。

var x = from y in SomeIQueryable 
     group y by y != null ? y.someForeignKey : null 
     into z 
     select z; 

將像上面那樣設置組會導致在針對實際SQL後備存儲運行時出現任何問題?

+1

不要在單元測試中使用數組,你會沒事的。當用數組或集合改變真正的實現時,你也在改變Linq provider =你的單元測試不會測試你的真實代碼。由於Linq-to-entities提供程序的性質不同,您已經發現單元測試失敗的情況,但更常見的情況是通過單元測試和失敗的運行時代碼,從而導致單元測試無用且不可靠。 –

+0

@LadislavMrnka您的評論是有用的,但它並不真正適用,除非測試的唯一要點是檢查查詢是否有效。 – hvd

+1

@ hvd:這就是爲什麼我把它寫成評論而不是答案。順便說一句。檢查查詢的工作意味着檢查它與你想在真實代碼中使用的提供者 - 這意味着不與虛假。 –

回答

0

我對這種檢查的經驗是,EF確實支持他們,將他們翻譯成正確的SQL。但是,生成的SQL將包含空檢查,並且至少在SQL Server上,該查詢的性能會稍差一些。對於複雜的查詢,它變得明顯。

但是,只要第二個表單在您的查詢中表現良好,可能就足夠了。

+0

這就是我所害怕的。 – Alwyn

0

一般來說,這樣的修改不應該引起任何問題。如果確實如此,那麼您將產生一個異常,聲稱底層提供程序出於某種原因無法將查詢轉換爲SQL。是的,任何問題都將是提供商特定的,並且沒有人能夠回答它。

對於新的T-SQL(SqlServer),它應該可以正常工作(IIRC),通過計算列 - 對於SQL,您提供的表達式恰好是:計算列。

Howeve喲umust非常小心與其他陷阱,對eaxmple當值和變量傳遞的null檢查不同的表現..

如果查詢只包含x != null那麼它將會被翻譯成x NOT NULL在SQL後端。但是如果你捕獲一個名稱的值,即使是本地的,即。 int? blah = null; .... from ... x != blah那麼EF將它傳送「錯誤地」爲x <> @param@param = NULL代碼將無法正常工作,想..

還有更多的C#<這種輕微的細微差別 - > SQL翻譯。但是,我沒有看到任何危險在你提供的確切代碼中。它看起來不錯。如果你嘗試過一次,並且它沒有扔出像NotSupportedException這樣的東西,那麼你可以認爲它會正常工作。如果linq提供者無法正確翻譯某些表達式,通常會拋出該類的異常。

+0

現在用'group by y.Length'嘗試一下,你會得到NRE,Alwyn試圖通過添加一個空檢查來避免。 – hvd

+0

哦基督。我誤解了這個問題,謝謝! – quetzalcoatl

+0

@Alwyn - 我已更新文字以符合實際問題。 – quetzalcoatl