我遇到了一个我没想到并需要帮助回答的场景。我们当前的系统调用SQL存储过程并因此创建SQL命令,添加参数并添加这些参数的值...比如插入。
我们的代码如下所示......
cmd.Parameters.Add("@MyTimestamp", SqlDbType.DateTime)
If MyObject.MyTimestamp <> Nothing Then
cmd.Parameters.Item("@MyTimestamp").Value = MyObject.MyTimestamp
Else
cmd.Parameters.Item("@MyTimestamp").Value = Nothing
End If
现在,当我第一次看到这个时,我有点惊讶MyObject.MyTimestamp曾经评估过Nothing,但它已存在多年没有问题。在清理工作期间,添加参数和设置其值的代码被组合在一起,因此上面的代码变成了......
cmd.Parameters.Add("@MyTimestamp", SqlDbType.DateTime).Value = If(MyObject.MyTimestamp <> Nothing, MyObject.MyTimestamp, Nothing)
对我而言,这看起来与代码最初所做的相同,但这不是测试期间发现的内容。在测试时我收到了一个SqlTypeException:
SqlDateTime溢出。必须在1/1/1753 12:00:00 AM和12/31/9999 11:59:59 PM之间。
这是因为使用If运算符将MyObject.MyTimestamp评估为不是Nothing,它不是DateTime.MinValue并且它试图将其插入到sql中并且它已经爆炸了。编写原始代码的方式将相同的Timestamp评估为Nothing(不确定如何/为什么)并执行false部分。所以我的问题是有什么区别,我应该关注其他数据类型......?
答案 0 :(得分:3)
记住(我经常不这样做)Nothing
不等同于C#中的null
,但更像是Default(T)
,以下内容不会检查MyObject.MyTimestamp是否已经过设置:
MyObject.MyTimestamp <> Nothing
但是在实际检查它是否是默认的日期时间(DateTime.MinValue),它可能总是如此。
此外,当您使用:
If(MyObject.MyTimestamp <> Nothing, MyObject.MyTimestamp, Nothing)
两种返回类型(MyObject.MyTimestamp
,Nothing
)必须属于同一类型,因此编译器知道MyObject.Timestamp
应该是一个日期时间,它不会将任何内容转换为默认日期时间
但是当你使用它时:
If MyObject.MyTimestamp <> Nothing Then
cmd.Parameters.Item("@MyTimestamp").Value = MyObject.MyTimestamp
Else
cmd.Parameters.Item("@MyTimestamp").Value = Nothing
End If
它识别"@MyTimestamp"
的参数属于SqlDbType.DateTime
类型,因此为此创建默认值。我不知道这是DbNull还是我头顶的实际值,但无论哪种方式都是允许的值,所以不会抛出错误。
另外,您可能希望将参数设置为DbNull.Value
而不是Nothing
:
If MyObject.MyTimestamp <> Nothing Then
cmd.Parameters.Item("@MyTimestamp").Value = MyObject.MyTimestamp
Else
cmd.Parameters.Item("@MyTimestamp").Value = DbNull.Value
End If