ExecuteScalar方法是ADO.NET的Command对象的一个重要方法,该方法实现执行查询并返回查询结果集中第一行第一列的值,返回值类型为object。当结果集中的第一行第一列为空时,该方法返回值为DBNull.Value。
例4.22 当ExecuteScalar返回值为空时的陷阱(光盘位置:光盘\MR\Instance\4\22\UseExecuteScalar),该实例的实现过程如下。
本实例实现统计某种商品的销售总量,并在控制台命令行中输出销售总量,本实例的Main方法实现获取商品的销售总量,并在控制台中输出,其代码如下:
在上面的代码中,用到了自定义方法GetSaleQuantity,该方法通过传入一条查询SQL语句来获取某种商品的销售总量,其代码如下:
在上面的代码中,ExecuteScalar方法返回某种商品的销售总量,若该商品还未发生销售,则该方法的返回值为DBNull.Value。若判断ExecuteScalar方法返回值为空,则自定义方法GetSaleQuantity返回值为0,否则返回实际某种商品的销售总量。编译后运行该程序,却出现如图4.43所示的异常提示。
图4.43 异常提示
DBNull.Value是DBNull类型的唯一实例,它的类型也为DBNull。
异常信息提示“可为空的对象必须具有一个值”,此处可为空的对象是指变量int Quantity,它是一个可空类型的变量。那么异常信息隐含的意思是变量intQuantity没有值,即值为空。但是我们知道,变量intQuantity的值是由ExecuteScalar方法的返回值转换而来的,若变量intQuantity的值为空,则ExecuteScalar方法的返回值必为DBNull.Value。由于这二者之间存在类型转换的关系,反向可以推断出intQuantity的值也为DBNull.Value,这样程序应该执行if语句块内的代码,而实际程序执行了else语句块内的代码。那么实际的情况是否真的像分析的这样吗?接下来添加对ExecuteScalar方法的快速监视,如图4.44所示。
从图4.44中可以看出,该方法的返回值类型为DBNull,即返回值为DBNull.Value,而变量intQuantity的值是由该方法的返回值转换而来的,那么变量intQuantity的值是否也为DBNull.Value呢?接下来添加对变量intQuantity的快速监视,如图4.45所示。
图4.44 快速监视
图4.45 快速监视
从图4.45中可以看出,变量intQuantity的值确实为null,而非DBNull.Value。这说明使用as运算符将DBNull.Value转换为可空类型时,其结果为null,而非DBNull.Value,这就是问题所在。
根据上面的分析,本实例采取两种方法来修改程序。
❏ 使用Nullable<int>类型的HasValue属性判断变量intQuantity是否有值,其代码如下:
❏ 使用null来做空值判断,代码如下: