2015-07-01 33 views
-2

我需要使用DataContext的ExecuteCommand方法對具有多個基礎表的View執行更新。由於在對具有多個基礎表的視圖執行此類操作時已知linqToSQL的限制,因此我正在使用此方法。如何將可空int轉換爲SQL空值?

我現有的SQL語句與以下類似,我將newFieldID設置爲null值僅僅是爲了說明這個問題。在應用程序中,newFieldID被分配一個傳遞的參數,實際上可以是一個整數值;但我的問題是特定於所提供的值是空類型的情況:

using (var _ctx = new MyDataContext()) 
{ 
    int? newFieldID = null; 
    var updateCmd = "UPDATE [SomeTable] SET fieldID = " + newFieldID + " 
    WHERE keyID = " + someKeyID; 

    try 
    { 
     _ctx.ExecuteCommand(updateCmd); 
     _ctx.SubmitChanges(); 
    } 
    catch (Exception exc) 
    { 
     // Handle the error... 
    } 
} 

此代碼將明顯的原因是,updateCmd不會爲空值的情況下完成失敗newFieldID。那麼如何用SQL空值替換或翻譯CLR空值來完成該語句?

我知道我可以將所有這些移動到一個存儲過程,但我正在尋找現有方案的答案。我嘗試過使用DBNull.Value進行實驗,但除了將其替換爲在語句中使用newFieldID的挑戰之外,只需將它放入字符串中即可打破語句的有效性。

此外,封閉成爲一個單引號內:

var updateCmd = "UPDATE [SomeTable] SET fieldID = '" + DBNull.Value + "' 
    WHERE keyID = " + someKeyID; 

將完成的發言,但該字段的值轉換爲整數0,而不是一個SQL空。

那麼,在這種情況下,如何將CLR null或null null轉換爲SQL Null值?

+1

請*不要*使用字符串連接。創建一個參數化查詢並按*原樣傳遞參數*。問題不在於如何轉換可空整數。 –

+1

首先,你應該使用參數化查詢。當newFieldID爲空時,您可以簡單地編寫「fieldID = null」。 – Plue

回答

1

嘗試檢查newFieldID == null並相應地更改語句。 像下面的東西或使用單獨的if/else語句。

var updateCmd = "UPDATE [SomeTable] SET fieldID =" + (newFieldID == null ? "null" : Convert.ToString(newFieldID)) + " WHERE keyID = " + someKeyID; 
1

通常,使用存儲過程或準備語句時,可以使用參數分配值。當您有DbParameter時,可以將nullDBNull.Value分配給Value-Property或您的參數。

如果你想擁有null如語句文本,只需使用SQL關鍵字NULL

var updateCmd = "UPDATE [SomeTable] SET fieldID = NULL WHERE keyID = " + someKeyID; 
4

正確的方式來做到這一點:使用ExecuteCommandoverride接受不但命令文本,而且陣參數和使用參數化查詢,而不是命令字符串連接:

var updateCmd = "UPDATE [SomeTable] SET fieldID = {0} WHERE keyID = {1}"; 
_ctx.ExecuteCommand(updateCmd, new [] {newFieldID, someKeyID}); 

它不僅可以防止你的SQL注入,而且它會做以下爲你(F rom MSDN description):

如果任何一個參數爲空,它將轉換爲DBNull.Value。

+0

我喜歡這個解決方案,但是如果參數值變化,你將如何實現它?換句話說,這裏的情況是一個整數,但假設參數列表推斷了一個可以包含整數,字符串和布爾值的隱式類型數組? – Mark

+0

@Mark由於第二個方法參數的類型是'object []' - 在這種情況下,只需使用顯式類型的對象數組:'new object [] {integerParam,stringParam,booleanParam}''。 –

+0

試圖在「查詢參數不能是'System.Object'類型'」中使用對象數組錯誤。任何想法爲什麼?這是.NET 4.5。儘管如此,我會接受你的答案,我喜歡它。 – Mark

0

正如安迪·科爾涅耶夫和其他人指出的那樣,一個參數數組的方法是最好的,可能是更合適的方法,使用的語句時。因爲我正在使用LinqToSQL,所以會提示帶有第二個參數的ExecuteCommand方法,該參數需要一個參數數組,但它的用法有以下注意事項。

  1. 查詢參數不能爲類型System.Nullable`1 [System.Int32] []
  2. 所有參數(我想在這種情況下,要解決的主要問題)必須是同一類型的

尚卡爾的答案雖然可以很快變得非常冗長,但參數的數量可能會增加。

所以我的問題的解決方法涉及使用參數的建議由Andy和Shankar的建議,通過創建一個幫助器方法來處理空值,這將採取帶有參數映射的SQL語句和實際參數。

幫助我的方法是:

private static string PrepareExecuteCommand (string sqlParameterizedCommand, object [] parameterArray) 
    { 
     int arrayIndex = 0; 
     foreach (var obj in parameterArray) 
     { 
      if (obj == null || Convert.IsDBNull(obj)) 
      { 
       sqlParameterizedCommand = sqlParameterizedCommand.Replace("{" + arrayIndex + "}", "NULL"); 
      } 
      else 
       sqlParameterizedCommand = sqlParameterizedCommand.Replace("{" + arrayIndex + "}", obj.ToString()); 
      ++arrayIndex; 
     } 
     return sqlParameterizedCommand; 
    } 

所以,現在我可以有潛在的空值這樣的參數執行我的發言:

int? newFieldID = null; 
int someKeyID = 12; 
var paramCmd = "UPDATE [SomeTable] SET fieldID = {0} WHERE keyID = {1}"; 
var newCmd = PrepareExecuteCommand(paramCmd, new object[] { newFieldID }); 

_ctx.ExecuteCommand(newCmd); 
_ctx.SubmitChanges(); 

這減輕了ExecuteCommand的兩個先前提到侷限性一個參數數組。空值被適當地轉換並且對象數組可以改變.NET類型。

我認爲尚卡爾的建議是答案,因爲它引發了這個想法,但發佈了我的解決方案,因爲我認爲它增加了更多的靈活性。