【问题标题】:Option Strict On and DBNull.ValueOption Strict On 和 DBNull.Value
【发布时间】:2016-11-03 19:08:14
【问题描述】:

我已经开始将我的应用程序转换为使用 Option Strict On。我一直在做CStr,Ctype等,进展顺利。

SQLCommand.Parameters.AddWithValue("@TERMINATE", If(IsNothing(txtEarningsTerminated.DateValue), DBNull.Value, txtEarningsTerminated.DateValue))

然后我打了这个。 txtEarningsTerminated.DateValue 是一个自定义屏蔽文本框。当它的值是 Nothing 我不想在数据库中存储任何东西。但是,它指出

Cannot infer a common type, and Option Strict On does not allow 'Object' to be assumed. 

当我将 DBNull.Value 更改为 "" 或什么都不更改时,错误就会消失。然而,作为 Nothing,它在运行时说明失败

The parameterized query '(@CONTROL int,@CLIENTCODE nvarchar(10),@NoBill int,@TERMINATE nv' expects the parameter '@TERMINATE', which was not supplied.

我想在数据库中放置一个 NULL。该值可以是日期,然后变为 NULL。

如何翻译这句话以免在 Option Strict On 下产生错误?

【问题讨论】:

  • 尝试在您的存储过程中为此参数设置一个默认的空值。
  • DbNullNothing 不同。不知道txtEarningsTerminated 是什么,因为它有一个DateValue 属性,但我怀疑它是可空的
  • txtEarningsTerminated.DateValue 是一个日期?
  • 有趣的是,当大多数 vb.net 开发人员开始时将 Option Strict 变为 On - C# 开发人员开始越来越多地使用 dynamic 关键字:)
  • 我花了一点时间,但我已将所有 AddWithValue 更改为仅添加。我还制作了一个程序来帮助改变。我不能在这里发布它,因为它与这个问题无关。现在,回到 Option Strict On 更改。

标签: vb.net visual-studio-2015 sql-server-2016


【解决方案1】:

原因是因为运算符If(condition, executeAndReturnIfTrue, executeAndReturnIfFalse) 期望truefalse 表达式都返回相同的类型。
在您的情况下,如果为 true,则返回 DbNull 类型,如果结果为 false,则返回 String(或您未提及的其他类型)。

如果更明确地创建SqlParameter,那么您可以使用下一种方法:

Dim value As Object = Nothing
If txtEarningsTerminated.DateValue Is Nothing Then
    value = DbNull.Value
Else
    value = xtEarningsTerminated.DateValue
End If

Dim param As SqlParameter = New SqlParameter With
{
    .ParameterName = "@TERMINATE",
    .SqlDbType = SqlDbType.VarChar, 'Or use your correct type
    .Value = value
}

正如在 cmets 中提到的那样,使用 AddWithValue 将强制 ADO.NET 为您的值自动确定 sql 类型,这可能会导致不同的问题。例如,每次您使用不同的值运行相同的查询时,每次更改值时都会重新编译查询计划。

你可以为string创建扩展方法

Public Module ExtensionsModule
    Public Function DbNullIfNothing(this As String) As Object
        If this Is Nothing Then Return DBNull.Value
        Return this
    End Function
End Module

然后用它代替你的“内联 If 方法”

Dim value As String = Nothing
Dim param As SqlParameter = New SqlParameter With
{
    .ParameterName = "@TERMINATE",
    .SqlDbType = SqlDbType.VarChar,
    .Value = value.DbNullIfNothing()
}

【讨论】:

  • 有点学究气,If() 不是函数而是运算符。
【解决方案2】:

所以答案很明显并且在错误中。我只需要将 DBNull.Value 封装在 Ctype 对象中

CType(DBNull.Value, Object)

然后代码就可以正常编译了。

【讨论】:

    【解决方案3】:

    这是一种方法(假设您在数据库中使用存储过程):

    1. 在您调用的存储过程中,将日期输入参数设置为 null,使其成为默认值为 null (@terminate DATETIME = NULL) 的可选字段。

    这样,如果您在过程调用中不包含该参数,则过程不会失败。

    1. 将日期字段的默认值设置为 DateTime.MinValue,使其始终具有一定的价值。然后您可以测试它是否等于 DateTime.MinValue 以外的日期。如果它是一个有效的日期值,则添加该行以将日期参数包含到过程调用中。如果等于 DateTime.MinValue,则不要在调用中添加参数。

    【讨论】:

    • SQL 语句很小,变成存储过程没有意义。在 C# 中,我可以使用 null 并且它可以工作。我想知道为什么我不能在这里这样做?
    • @Kayot AddWithValue 可以给出问题:Can we stop using AddWithValue() already?。 (以及使您的程序符合 Option Strict On 的荣誉。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 2012-09-04
    • 1970-01-01
    相关资源
    最近更新 更多