2012-11-19 111 views
55

我有以下代碼來指定SQL查詢的參數。當我使用Code 1;但使用Code 2時效果很好。在Code 2我們有一個空的檢查,因此if..else塊。AddWithValue參數爲NULL時出現異常

例外:

的參數化查詢 '(@application_ex_id nvarchar的(4000))選擇E.application_ex_id A' 預計參數 '@application_ex_id',但未提供。

代碼1

command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 

代碼2

if (logSearch.LogID != null) 
{ 
     command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
} 
else 
{ 
     command.Parameters.AddWithValue("@application_ex_id", DBNull.Value); 
} 

QUESTION

  1. 您能解釋爲什麼它不能從代碼1中的logSearch.LogID值中獲取NULL(但能夠接受DBNull)?

  2. 有沒有更好的代碼來處理呢?

參考

  1. Assign null to a SqlParameter
  2. Datatype returned varies based on data in table
  3. Conversion error from database smallint into C# nullable int
  4. What is the point of DBNull?

代碼

public Collection<Log> GetLogs(LogSearch logSearch) 
    { 
     Collection<Log> logs = new Collection<Log>(); 

     using (SqlConnection connection = new SqlConnection(connectionString)) 
     { 
      connection.Open(); 

      string commandText = @"SELECT * 
       FROM Application_Ex E 
       WHERE (E.application_ex_id = @application_ex_id OR @application_ex_id IS NULL)"; 

      using (SqlCommand command = new SqlCommand(commandText, connection)) 
      { 
       command.CommandType = System.Data.CommandType.Text; 

       //Parameter value setting 
       //command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
       if (logSearch.LogID != null) 
       { 
        command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID); 
       } 
       else 
       { 
        command.Parameters.AddWithValue("@application_ex_id", DBNull.Value); 
       } 

       using (SqlDataReader reader = command.ExecuteReader()) 
       { 
        if (reader.HasRows) 
        { 
         Collection<Object> entityList = new Collection<Object>(); 
         entityList.Add(new Log()); 

         ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader); 

         for (int i = 0; i < records.Count; i++) 
         { 
          Log log = new Log(); 
          Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i]; 
          EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord); 
          logs.Add(log); 
         } 
        } 

        //reader.Close(); 
       } 
      } 
     } 

     return logs; 
    } 
+3

你是什麼意思更好?代碼2是向數據庫發送空值的正確方法。 –

+0

參考:http://stackoverflow.com/questions/13265704/conversion-error-from-database-smallint-into-c-sharp-nullable-int – Lijo

回答

84

煩人,不是嗎。

您可以使用:

command.Parameters.AddWithValue("@application_ex_id", 
     ((object)logSearch.LogID) ?? DBNull.Value); 

或者,使用像「短小精悍」的工具,這將盡一切搞亂你。

例如:

var data = conn.Query<SomeType>(commandText, 
     new { application_ex_id = logSearch.LogID }).ToList(); 

誘惑添加一個方法短小精悍得到IDataReader ......真的不知道還是否是一個好主意。

+0

@Phil確實;大多數東西都可以......但我不喜歡在'object'中添加擴展方法,而且我們也看不到'是否可空''vs'string'等等......但是:它可以很容易地完成足夠。 –

+1

我在想'參數'屬性的擴展 - 是'對象'嗎? –

+3

@Phil嗯,是的,它是的,我明白你的意思......也許'AddWithValueAndTreatNullTheRightDamnedWay(...)' –

1

一些問題,以允許必然設置SQLDbType

command.Parameters.Add("@Name", SqlDbType.NVarChar); 
command.Parameters.Value=DBNull.Value 
其中SqlDbType.NVarChar鍵入

。必需設置的SQL類型。 Enjou

34

我覺得它更容易只寫一個處理空值SqlParameterCollection擴展方法:

public static SqlParameter AddWithNullableValue(
    this SqlParameterCollection collection, 
    string parameterName, 
    object value) 
{ 
    if(value == null) 
     return collection.AddWithValue(parameterName, DBNull.Value); 
    else 
     return collection.AddWithValue(parameterName, value); 
} 

然後你只需把它想:

sqlCommand.Parameters.AddWithNullableValue(key, value); 
+0

_value_可以是** int或int?,string,bool或bool?,DateTime或Datetime?**等? – Kiquenet

+0

@Kiquenet是的... – AxiomaticNexus

+2

我讀馬克的回答,認爲「我想我寧願只寫參數集合的擴展方法」,然後我向下滾動頭髮...(妙處擴展方法是我可以做一個單一的查找/替換後,我所有的代碼更新完成) – jleach

2

萬一你」在調用存儲過程時重新執行此操作:如果您在參數上聲明瞭默認值並僅在必要時才添加它,則認爲它更易於閱讀。

例如: (SQL)

DECLARE PROCEDURE myprocedure 
    @myparameter [int] = NULL 
AS BEGIN 

(C#)

int? myvalue = initMyValue(); 
if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue); 

我知道這是老了,但我覺得這是有益的,想和大家分享。

-3

創建一個靜態類是這樣的:

public static class Extensions 
{ 
    public static string RemoveNulls(this string container) 
    { 
     if (container == null) 
      container = ""; 
     return container; 
    } 
} 

然後在你的代碼,這樣做:

Parameters.AddWithValue(sName, Value.RemoveNulls()); 

這是防彈,非常容易使用

+1

這將插入「」而不是空... – Lars

+0

這就是他想要的 - 不輸入空值 – TheWizardOfTN

相關問題