2009-05-14 13 views
22

データベース(SQL Server)でnullになる可能性のあるパラメータを持つSQLクエリがあります。そのユーザーがフィールドに空白を入れるまで、updateメソッドは正常に動作します。これにより、DataTimeオブジェクトのNULL値が生成されます(このオブジェクトはNULL可能です)。問題は、dbCommand.ExecuteNonQuery();です。ここでNullable値を持つSqlParameterはExecuteNonQuery中にエラーを返しますか?

は、私がこのフィールドにパラメータを構築する方法である:

IDataParameter dbParam_au_id = new SqlParameter(); 
    dbParam_au_id.ParameterName = "@birthday"; 
    dbParam_au_id.Value = birthday; 
    dbParam_au_id.DbType = DbType.DateTime; 
    dbCommand.Parameters.Add(dbParam_au_id); 

私はそのようにDBNull.Valueのに誕生日のnull値を変換しようとしている:

IDataParameter dbParam_au_id = new SqlParameter(); 
    dbParam_au_id.ParameterName = "@birthday"; 
    dbParam_au_id.Value = birthday??DBNull.Value; 
    dbParam_au_id.DbType = DbType.DateTime; 
    dbCommand.Parameters.Add(dbParam_au_id); 

しかし、このコードウォンコンパイルするとエラーが発生する:

エラー1オペレータ '??'型 'System.DateTime?'のオペランドには適用できません。と 'System.DBNull'

ご存知ですか?

+0

出力パラメータとして使用しない限り、DbTypeプロパティを設定しないことを強くお勧めします。私は一度もそれを使って解決した無数の微妙なバグを見たことはありませんでした。 –

答えて

51

種類は互換性がありません。 SqlParameterクラスが正しく初めて書かれていた場合... C#のNULL値がDBNull.Valueのように扱われることになる

dbParam_au_id.Value = (object)birthday ?? DBNull.Value; 
13

:このような何かを試してみてください。これは直感的なので、コースのSqlParameter値をnullに設定することは、SqlParameterCollectionからSqlParameter値を削除することと機能的に同等です。

このばかばかしいAPI設計エラーを修正するには、SqlParameterCollection、String(パラメータ名)、およびObject(パラメータ値)を取る独自のAddParameterメソッド(オーバーロードあり)を作成します。あなたが見ることができるように

#region Add by Name/Value. 
/// <summary> 
/// Adds an input parameter with a name and value. Automatically handles conversion of null object values to DBNull.Value. 
/// </summary> 
/// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> 
/// <param name="name">The name of the parameter to add.</param> 
/// <param name="value">The value of the parameter to add.</param> 
private static void AddParameter(SqlParameterCollection parameters, string name, object value) 
{ 
    parameters.Add(new SqlParameter(name, value ?? DBNull.Value)); 
} 

/// <summary> 
/// Adds a parameter with a name and value. You specify the input/output direction. Automatically handles conversion of null object values to DBNull.Value. 
/// </summary> 
/// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> 
/// <param name="name">The name of the parameter to add.</param> 
/// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> 
/// <param name="direction">The ParameterDirection of the parameter to add (input, output, input/output, or return value).</param> 
private static void AddParameter(SqlParameterCollection parameters, string name, object value, ParameterDirection direction) 
{ 
    SqlParameter parameter = new SqlParameter(name, value ?? DBNull.Value); 
    parameter.Direction = direction; 
    parameters.Add(parameter); 
} 
#endregion 

#region Add by Name, Type, and Value. 
/// <summary> 
/// Adds an input parameter with a name, type, and value. Automatically handles conversion of null object values to DBNull.Value. 
/// </summary> 
/// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> 
/// <param name="name">The name of the parameter to add.</param> 
/// <param name="type">Specifies the SqlDbType of the parameter.</param> 
/// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> 
private static void AddParameter(SqlParameterCollection parameters, string name, SqlDbType type, object value) 
{ 
    AddParameter(parameters, name, type, 0, value ?? DBNull.Value, ParameterDirection.Input); 
} 

/// <summary> 
/// Adds a parameter with a name, type, and value. You specify the input/output direction. Automatically handles conversion of null object values to DBNull.Value. 
/// </summary> 
/// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> 
/// <param name="name">The name of the parameter to add.</param> 
/// <param name="type">Specifies the SqlDbType of the parameter.</param> 
/// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> 
/// <param name="direction">The ParameterDirection of the parameter to add (input, output, input/output, or return value).</param> 
private static void AddParameter(SqlParameterCollection parameters, string name, SqlDbType type, object value, ParameterDirection direction) 
{ 
    AddParameter(parameters, name, type, 0, value ?? DBNull.Value, direction); 
} 
#endregion 

#region Add by Name, Type, Size, and Value. 
/// <summary> 
/// Adds an input parameter with a name, type, size, and value. Automatically handles conversion of null object values to DBNull.Value. 
/// </summary> 
/// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> 
/// <param name="name">The name of the parameter to add.</param> 
/// <param name="type">Specifies the SqlDbType of the parameter.</param> 
/// <param name="size">Specifies the size of the parameter for parameter types of variable size. Set to zero to use the default size.</param> 
/// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> 
private static void AddParameter(SqlParameterCollection parameters, string name, SqlDbType type, int size, object value) 
{ 
    AddParameter(parameters, name, type, size, value ?? DBNull.Value, ParameterDirection.Input); 
} 

/// <summary> 
/// Adds a parameter with a name, type, size, and value. You specify the input/output direction. Automatically handles conversion of null object values to DBNull.Value. 
/// </summary> 
/// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> 
/// <param name="name">The name of the parameter to add.</param> 
/// <param name="type">Specifies the SqlDbType of the parameter.</param> 
/// <param name="size">Specifies the size of the parameter for parameter types of variable size. Set to zero to use the default size.</param> 
/// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> 
/// <param name="direction">The ParameterDirection of the parameter to add (input, output, input/output, or return value).</param> 
private static void AddParameter(SqlParameterCollection parameters, string name, SqlDbType type, int size, object value, ParameterDirection direction) 
{ 
    SqlParameter parameter; 
    if (size < 1) 
     parameter = new SqlParameter(name, type); 
    else 
     parameter = new SqlParameter(name, type, size); 
    parameter.Value = value ?? DBNull.Value; 
    parameter.Direction = direction; 
    parameters.Add(parameter); 
} 
#endregion 

は、値がすでにオブジェクトとして型指定された方法(および過負荷)、内部で、私は強制する「値?? DBNull.Valueの」ステートメントを使用し、ヌル= DBNull.Valueをルール。

null値のオブジェクト参照またはnullのない型をAddParameterメソッドに渡すと、DBNull.Valueがクエリに渡される予想通りの直感的な動作が得られます。

私はパラメータが無視されるようにしたい場合、私はそれを追加せずにそれをnullに設定するので、APIがそのまま実装された理由を想像できません。私は最初にそれを追加しないか、SqlParameterCollectionから削除します。パラメータを追加してSETに値を設定しても(nullに設定されていても)、クエリでUSEDになると予想されます。null値を意味するnullが必要です。

パフォーマンス上の理由から「正しい」方法を実装していないと聞いたことがありますが、SqlParameterCollection.AddWithValueメソッドを呼び出すと、すべてがオブジェクトに変換されて、Nullableインスタンスはnoヌルオブジェクトへの値は、パフォーマンスヒットではないC#言語の本質的な部分です。 Microsoftはこれを実際に修正する必要があります。

+1

ユーティリティ機能の素敵なセット。 3.5以上であれば、これらをSqlParameterCollectionの拡張機能に調整することができ、command.Paramters.AddParameter(...)エクスペリエンスは – Roman

+0

になります。7年後、これは依然としてSqlParameterCollection Addメソッドの動作です。あなたはまだこのソリューションを使用していますか?その間により良い修正が行われたかどうかは不思議です。私は現在、パラメータ配列でAddRangeを使用しているので、配列をループしてnullの場合はそれぞれの値を置き換える必要があります。 – Doug

関連する問題