web-dev-qa-db-ja.com

SqlCommand-ExecuteScalarエラー処理でintにキャストします

壊れやすいコードがあります。このステートメントはこちら

 int countDis = (int)cmd.ExecuteScalar();

ストアドプロシージャを変更して何も返さないようにすると、そのキャストは(int)が爆発します。単に削除すると、コンパイルできません。

この状況での防御的コーディングの最良のコードプラクティスは何ですか?

11
user5299399

次のようにコードを変更してください:

_int countDis = Convert.ToInt32(cmd.ExecuteScalar());
_

これにより、ストアドプロシージャで何も選択しなかった結果としてExecuteScalarnullを返した場合でも、countDisの値は_0_になります。なぜならConvert.ToInt32(null) = 0だからです。

更新(2018年12月12日)

安全なバージョン。 DBNullケースを強調してくれて@Moeに感謝します。

_object result = cmd.ExecuteScalar();
result = (result == DBNull.Value) ? null : result;
int countDis = Convert.ToInt32(result);
_
22
Nikhil Vartak

キャストする前にスカラー値を確認できます。

var result = cmd.ExecuteScalar();
int countDis =result != null ? int.Parse(result) : 0;

通常、null許容型を使用します。例えば:

string str;

int? countDis = cmd.ExecuteScalar() as int?;
if (countDis == null)
   str = "count is null";
else
   str = "Count is : " + countDis.Value;

これは、ExecuteScalarがnullまたはDBNull.Valueを返すかどうかに関係なく機能します。

3
Moe Sisko

_DBNull.Value_の結果をnullと同じように扱うと、どちらも_0_になるはずですが、一時変数を使用しているにもかかわらず、1行を使用できます。実行速度については触れません。

int countDis = int.TryParse(cmd.ExecuteScalar()?.ToString(), out int temp) ? temp : 0

1
Conner

ExecuteScalarはDBNullを返すことができるため、私が見つけた最良の方法は次のとおりです。

 var result = cmd.ExecuteScalar();
 int countDis = result != null ? Convert.ToInt32(result) : 0;
1
Hamlet Mendez

を使用してObjectとして取得し、そのタイプを確認してから決定することができます。

        object obj = cmd.ExecuteScalar();
        if (obj.GetType() == typeof(string))
        {
            //you can do your stuff with STRING
        }
        else if (obj.GetType() == typeof(int))
        {
            //you can do your stuff with INT
        }
        else
        {
            //add here ANYOTHER type you many want in future...
        }
0
M_Idrees