为什么SqlParameter名称/值构造函数将0视为null?

时间:2011-12-02 05:48:07

标签: c# sql-server ado.net sqlparameter

我在一段代码中发现了一个奇怪的问题,即即使其参数与数据源中的记录匹配,但adhoc SQL查询未产生预期的输出。我决定将以下测试表达式输入到即时窗口中:

new SqlParameter("Test", 0).Value

这导致null的结果,让我挠头。似乎SqlParameter构造函数将零视为空值。以下代码生成正确的结果:

SqlParameter testParam = new SqlParameter();
testParam.ParameterName = "Test";
testParam.Value = 0;
// subsequent inspection shows that the Value property is still 0

任何人都可以解释这种行为吗?这是故意的吗?如果是这样,那可能相当危险......

2 个答案:

答案 0 :(得分:30)

如该构造函数的documentation中所述:

  

在value参数中指定Object时,将从Object .NET的Microsoft .NET Framework类型推断出SqlDbType。

     

使用SqlParameter构造函数的此重载指定整数参数值时请小心。因为此重载采用Object类型的值,所以当值为零时,必须将整数值转换为Object类型,如下面的C#示例所示。

Parameter = new SqlParameter("@pname", (object)0);
     

如果您不执行此转换,编译器会假定您尝试调用SqlParameter (string, SqlDbType)构造函数重载。

你只是在调用一个不同于你案例的构造函数。

原因是C#允许从整数文字0进行隐式转换为枚举类型(下面只是整数类型),这种隐式转换会导致{{ 1}}构造函数是重载决策的最佳匹配,而不是为(string, SqlDbType)构造函数转换intobject所需的装箱转换。

当您传递(string, object) 变量时,即使该变量的值为int(因为它不是零文字),这也不会成为问题,或任何其他类型为0的表达式。如果你明确地将int强制转换为int,也不会发生这种情况,因为那时只有一个匹配的重载。

答案 1 :(得分:6)

在传递/添加参数时使用类型化数据是一种很好的做法。

您可以通过以下方式完成以下任务:

对于string / varchar类型的数据:

SqlParameter pVarchar = new SqlParameter
                    {
                        ParameterName = "Test",
                        SqlDbType = System.Data.SqlDbType.VarChar,
                        Value = string.Empty,
                    };

对于int类型数据:

SqlParameter pInt = new SqlParameter
                    {
                        ParameterName = "Test",
                        SqlDbType = System.Data.SqlDbType.Int,
                        Value = 0,
                    };

您可以根据使用的数据更改SqlDbType的值。