2016-05-10 103 views
1

使用:實體框架4.3.1,MVC 4空VS默認設置爲空 - 讓不同的結果

示例數據庫記錄(例如):

 
Id Height 
1  null 
2  2.1 

爲什麼第一條語句會帶回零結果:

decimal? scannedItemHeight = default(decimal?); 

(from st in Stocks 
where st.Height == scannedItemHeight 
select st.Id).ToList(); 

但是,此語句返回記錄ID 1:

(from st in Stocks 
where st.Height == null 
select st.Id).ToList(); 

如果scannedItemHeight爲空,我只想匹配高度爲零的值。

我只想要回的第一條記錄,ID爲1

UPDATE 我最終使用:

st.Height == scannedItemHeight || (scannedItemHeight == null && st.Height == null) 
+0

日誌中生成實際的SQL語句,看看是否有區別。 HTTP://計算器。com/questions/16880687/how-can-i-log-the-generated-sql-from-dbcontext-savechanges-in-my- –

+1

你是否確實擁有與其他條件匹配的非空高度的項目?否則,這兩種方法的結果在_this_中是相同的(因爲Jon的方法只會返回Height爲空的項目,而我的方法只是返回所有項目)。理解這些方法之間的區別非常重要。因爲我不知道如果參數爲null,所以需要使用null Height匹配項目 - 所以使用Jon的方法。 – Evk

+0

@Evk Doh!我認爲你的權利,我選擇了高度的例子,並沒有檢查其他給定的過濾參數(寬度,長度,表),所有的結果有一個空的高度,讓我重新測試並找回你,但是的,這將解釋一切。 –

回答

3

這是因爲在第一種情況下數據庫查詢會是這樣的

where Height = @param1 ... 

而在第二種情況下,這將是

where Height is null 

第一個查詢將不返回結果,因爲@param1將爲空,並且沒有行可以匹配此類條件。

要點是,從C#的角度來看,這些查詢是等價的,但從sql的角度來看,它們不是:您應該在sql中使用IS NULL(或IS NOT NULL)來檢查空值。

如何解決取決於當你的參數爲null時你想做什麼。在你的情況下:使用Jon Skeet的回答

如果有人想要忽略參數並且根本不需要過濾(比較常見的情況,例如當參數表示用戶在某個域中的輸入,以及當沒有輸入任何內容時 - 無需過濾),則執行:

where scannedItemHeight == null || st.Height == scannedItemHeight 

這將是SQL像

where @param1 is null OR Height = @param1 
+0

嗯...有道理...所以我怎麼能通過一個空值的空可變十進制變量,它被視爲'爲空'? –

+0

@PaulZahra查看更新 – Evk

+0

掛起 - 這會給出錯誤的結果,當然......如果'scannedItemHeight'爲空,大概OP *只*要匹配其中st.Height'爲空的值,而這將包括st.Height'具有任何價值的值... –

3

我當然看到了一些奇怪的LINQ的行爲之前,現在,由於SQL處理空值的方式與C#處理空值的方式不同。在C#中,如果ab都爲空,則在a == b中爲真;而在SQL中,它們不是...而是必須有意檢查是否爲空。我會嘗試:

var temp = (from st in Stocks 
      where st.Height == scannedItemHeight || (scannedItemHeight == null && st.Height == null) 
      select st.Id).ToList(); 

或不同構建查詢:

var filtered = scannedItemHeight == null 
    ? Stocks.Where(st => st.Height == null) 
    : Stocks.Where(st => st.Height == scannedItemHeight); 
var temp = filtered.Select(st => st.Id).ToList(); 
相關問題