简体   繁体   English

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

[英]Why does the SqlParameter name/value constructor treat 0 as null?

I observed a strange problem in a piece of code where an adhoc SQL query was not producing the expected output, even though its parameters matched records in the data source.我在一段代码中观察到一个奇怪的问题,即即席 SQL 查询没有产生预期的输出,即使其参数与数据源中的记录匹配。 I decided to enter the following test expression into the immediate window:我决定在即时窗口中输入以下测试表达式:

new SqlParameter("Test", 0).Value

This gave a result of null , which leaves me scratching my head.这给出了null的结果,这让我摸不着头脑。 It seems that the SqlParameter constructor treats zeroes as nulls.似乎SqlParameter构造函数将零视为空值。 The following code produces the correct result:以下代码产生正确的结果:

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

Can anyone explain this behaviour?谁能解释这种行为? Is it somehow intentional?不知是不是故意的? If so, it's potentially rather dangerous...如果是这样,那可能是相当危险的......

As stated in the documentation for that constructor:如该构造函数的文档中所述:

When you specify an Object in the value parameter, the SqlDbType is inferred from the Microsoft .NET Framework type of the Object.当您在 value 参数中指定一个 Object 时,SqlDbType 是从 Object 的 Microsoft .NET Framework 类型推断出来的。

Use caution when you use this overload of the SqlParameter constructor to specify integer parameter values.使用SqlParameter构造函数的此重载指定整数参数值时要小心。 Because this overload takes a value of type Object , you must convert the integral value to an Object type when the value is zero, as the following C# example demonstrates.由于这种重载采用类型的值对象,则必须将整数值转换为对象的类型,如果值是零,如下面的C#示例演示。

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

If you do not perform this conversion, the compiler assumes that you are trying to call the SqlParameter (string, SqlDbType) constructor overload.如果不执行此转换,编译器会假定您正在尝试调用SqlParameter (string, SqlDbType)构造函数重载。

You simply were calling a different constructor than you thought in your case.您只是调用了与您的情况不同的构造函数。

The reason for this is that C# allows an implicit conversion from the integer literal 0 to enum types (which are just integral types underneath), and this implicit conversion causes the (string, SqlDbType) constructor to be a better match for overload resolution than the boxing conversion necessary to convert int to object for the (string, object) constructor.这样做的原因是,C#允许从整数字面的隐式转换0到枚举类型(这只是整数类型的下面),并且这隐式转换导致(string, SqlDbType)构造成为过载的分辨率比更好的匹配为(string, object)构造函数将int转换为object所需的装箱转换。

This will never be a problem when you pass an int variable , even if the value of that variable is 0 (because it is not a zero literal), or any other expression that has the type int .当您传递int变量时,这永远不会成为问题,即使该变量的值为0 (因为它不是零文字),或任何其他具有int类型的表达式。 It will also not happen if you explicitly cast the int to object as seen above, because then there is only one matching overload.如果您如上所示将int显式转换为object ,也不会发生这种情况,因为只有一个匹配的重载。

It is good practices to use typed data while passing/adding your parameters.在传递/添加参数时使用类型化数据是一种很好的做法。

Below way you can accomplish the task as below:您可以通过以下方式完成以下任务:

For string/varchar typed data:对于字符串/varchar 类型的数据:

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

For int typed data:对于 int 类型数据:

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

You can change the value of SqlDbType according to your used data.您可以根据您使用的数据更改SqlDbType的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM