2012-11-19 15 views
55

SQLクエリのパラメータを指定する次のコードがあります。 Code 1を使用すると例外になります。私がCode 2を使用すると正常に動作します。 Code 2にはnullのチェックがあり、したがってif..elseブロックがあります。AddWithValueパラメータがNULLの場合の例外

例外:

パラメータ化クエリ供給されなかった '@application_ex_id' パラメータを、期待 '(@application_ex_idのnvarchar(4000))E.application_ex_id Aを選択します'。

コード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

を使用することは非常に簡単です:これを行う、あなたのコードに続いて

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

をより良い?コード2は、データベースにNULL値を送信する正しい方法です。 –

+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); 

またはその代わりに、あなたのためのいじりすべてのことを行います「Dapperの」のようなツールを使用します。例えば

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

私はが、それは良い考えであるかどうか、まだ本当にわからないIDataReaderを...得るためにはdapperためにメソッドを追加するを誘惑です。

+0

@Phil確かに;ほとんどのことができるのですが、 'object'に拡張メソッドを追加するのが好きではなく、' Nullable 'vs' string'などのようには見えませんが、それは簡単にできます十分な。 –

+1

私は 'Parameters'プロパティの拡張を考えていました - それは' Object'ですか? –

+3

@Phil hmmm、そうです、あなたが何を意味するのか見てみましょう。おそらく 'AddWithValueAndTreatNullTheRightDamnedWay(...) ' –

1

必ずしもSqlDbType.NVarCharは、あなたが入力し

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

なSQLDbType

を設定して許可され、いくつかの問題、。必ずSQL型を設定します。

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); 
34

ストアドプロシージャを呼び出す際にこれをやり直してください。パラメータにデフォルト値を宣言し、必要なときにだけ追加すると読みやすくなります。例えば

: (SQL)

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

(C#の)

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

私は、これは古いですけど、私はこの参考と共有したいと思いました。

+0

_value_は** intまたはint?、string、boolまたはbool?、DateTimeまたはDatetime?**などです。 – Kiquenet

+0

@Kiquenetはい... – AxiomaticNexus

+2

私はMarcの答えを読んで、 "私はちょうどパラメータコレクションの拡張メソッドを書くと思う"と思って、次に髪をスクロールしました...(拡張メソッドについての素晴らしい点は、私は1つの検索/置換をやり直すことができますし、すべてのコード更新が完了しました) – jleach

2

単に」の場合、あなたの中で、私はそれが簡単だけでnull値を扱うSqlParameterCollectionための拡張メソッドを記述するために見つける 炎上

-3

このような静的クラスを作成します。

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

これは防弾、あなたは何を意味するん

+1

これは ""とヌルを挿入しません... – Lars

+0

これは彼が望むものです - ヌルを入力しないでください – TheWizardOfTN