在 SqlCommand-ExecuteScalar 错误处理上转换为 int

Cast to int on SqlCommand-ExecuteScalar error handling

我的代码可能很脆弱。此处声明

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

如果我将存储过程更改为不 return 任何东西,那么转换为 (int) 将会失败。如果我简单地删除它,那么我就无法编译。

在这种情况下,防御性编码的最佳代码实践是什么?

您可以在投射前检查标量值。

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

只需将代码更改为:

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

这将确保即使 ExecuteScalar returns null,由于未在存储过程中选择任何内容,countDis 的值也会是 0.因为Convert.ToInt32(null) = 0.

更新 (10/12/2018)

更安全的版本。感谢@Moe 强调 DBNull 案例。

object result = cmd.ExecuteScalar();
result = (result == DBNull.Value) ? null : result;
int countDis = Convert.ToInt32(result);

您可以使用 get as 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...
        }

我通常使用可空类型。例如:

string str;

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

这将适用于 ExecuteScalar returns null 或 DBNull.Value。

因为 ExecuteScalar 可以 return DBNull,所以我找到的最好的方法是:

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

如果您将 DBNull.Value 的结果视为与 null 相同的结果,因为它们都应该是 0,您可以使用单行,尽管您仍在使用一个临时变量。执行速度就不说了:

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