32

我在一段代码中观察到一个奇怪的问题,即即席 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

谁能解释这种行为?是不是故意的?如果是这样,它可能相当危险......

4

2 回答 2

37

如该构造函数的文档中所述:

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

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

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

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

您只是在调用与您的情况不同的构造函数。

这样做的原因是 C# 允许从整数文字到枚举类型的隐式0转换(它们只是下面的整数类型),并且这种隐式转换导致(string, SqlDbType)构造函数比转换int为所需的装箱转换更适合重载解析object对于(string, object)构造函数。

int 当您传递一个variable时,这永远不会成为问题,即使该变量的值是0(因为它不是零字面量),或者任何其他具有 type 的表达式int。如果您如上所示显式int转换 to ,也不会发生这种情况object,因为只有一个匹配的重载。

于 2011-12-02T05:50:33.573 回答
6

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

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

对于字符串/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您可以根据使用的数据更改 的值。

于 2011-12-02T06:15:06.987 回答