为啥SqlParameter名称/值构造函数将0视为null?
Posted
技术标签:
【中文标题】为啥SqlParameter名称/值构造函数将0视为null?【英文标题】:Why does the SqlParameter name/value constructor treat 0 as null?为什么SqlParameter名称/值构造函数将0视为null? 【发布时间】:2012-01-11 05:48:54 【问题描述】:我在一段代码中观察到一个奇怪的问题,即即席 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
谁能解释这种行为?是不是故意的?如果是这样,那可能是相当危险的......
【问题讨论】:
关于这个主题的进一步阅读:***.com/questions/14224465/… 【参考方案1】:正如documentation 中针对该构造函数所述:
当您在 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
变量 时,这绝不会成为问题,即使该变量的值是0
(因为它不是零字面量)或任何其他表达式类型为int
。如果您如上所示将int
显式转换为object
,也不会发生这种情况,因为只有一个匹配的重载。
【讨论】:
我遇到了这个问题并尝试了一个不起作用的不同解决方案:为什么我尝试的Parameter = new SqlParameter("@pname", (int)0);
不起作用时建议的 Parameter = new SqlParameter("@pname", Convert.ToInt32(0));
起作用?
@mortb,您必须为此查阅语言规范,但我的猜测是,重载解析在第一种情况下会关心确切的类型,但在第二种情况下可能允许枚举,因为您' 仍在传递int
类型的文字。
我找到了原因:***.com/questions/3153841/… 文字 0 将始终被评估为匹配枚举的类型,而其他数字则不会。似乎有点晦涩...
引用的示例有问题:Convert.ToInt32(0)
不会更改选择的重载。代码应该是new SqlParameter("@pname", (object)0);
。
@Steven:如果我错了,请纠正我,但只有 literal 0
可以隐式转换为任何枚举类型。因此,返回int
的方法调用很好,可以选择另一个重载。不可否认,自从我查看规范以来已经有几个月了,但是 afaik 它就是这样工作的。【参考方案2】:
在传递/添加参数时使用类型化数据是一种很好的做法。
您可以通过以下方式完成以下任务:
对于字符串/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
的值。
【讨论】:
虽然通常很有帮助,但从技术上讲,这并不是问题的答案。因此它应该是一个评论。以上是关于为啥SqlParameter名称/值构造函数将0视为null?的主要内容,如果未能解决你的问题,请参考以下文章