C# SqlCommand ExecuteScalar错误处理时强制转换为int

C# SqlCommand ExecuteScalar错误处理时强制转换为int,c#,sql,sql-server,ado.net,C#,Sql,Sql Server,Ado.net,我有可能是脆弱的代码。这句话 int countDis = (int)cmd.ExecuteScalar(); 如果我将存储过程更改为不返回任何内容,则转换为(int)的操作将失败。如果我只是删除它,那么我就无法编译 在这种情况下,防御编码的最佳代码实践是什么?您可以在强制转换之前检查标量值 var result = cmd.ExecuteScalar(); int countDis =result != null ? int.Parse(result) : 0; 只需将代码更改为: in

我有可能是脆弱的代码。这句话

 int countDis = (int)cmd.ExecuteScalar();
如果我将存储过程更改为不返回任何内容,则转换为
(int)
的操作将失败。如果我只是删除它,那么我就无法编译


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

您可以在强制转换之前检查标量值

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

只需将代码更改为:

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

更新(2018年12月10日)

更安全的版本。感谢@Moe突出显示
DBNull
案例

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

您可以使用获取作为对象,并检查其类型,然后作出决定:

        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...
        }

我通常使用可空类型。e、 g:

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

因为ExecuteScalar可以返回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

使用like
int?
您可以检查这些:如果您将存储过程更改为不返回任何内容,那么您最好使用
cmd.ExecuteNonQuery
,我想。我更改它只是为了测试,它应该总是返回一个计数intSQL Server存储过程不能返回除
int
以外的任何东西作为其返回值-所以这真的不是一个问题…敏捷方法学会说您应该只针对当前问题进行编码。这也被称为YAGNI(你不需要它)原则。当然,我个人也不喜欢这一点,但我在这里只是想说明一下@MillRunnerExecuteScalar可以返回DBNull.Value,如果结果集中有一行,但列的值是数据库NULL。在这种情况下,将使用上述代码引发InvalidCastException。如果结果集中没有可从中提取列值的行,ExecuteScalar可以返回null(即C#null)。