Vb.net 选项Strict On和DBNull.Value

Vb.net 选项Strict On和DBNull.Value,vb.net,visual-studio-2015,sql-server-2016,Vb.net,Visual Studio 2015,Sql Server 2016,我已经开始将我的一个应用程序转换为使用Option Strict On。我一直在做CStr,Ctype等,进展顺利 SQLCommand.Parameters.AddWithValue("@TERMINATE", If(IsNothing(txtEarningsTerminated.DateValue), DBNull.Value, txtEarningsTerminated.DateValue)) 然后我打了这个。txtEarningsTerminated.DateValue是一个自定义屏蔽

我已经开始将我的一个应用程序转换为使用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更改为“”或无任何内容时,错误消失。但是,由于没有什么,它在运行时声明期间失败

The parameterized query '(@CONTROL int,@CLIENTCODE nvarchar(10),@NoBill int,@TERMINATE nv' expects the parameter '@TERMINATE', which was not supplied.
我想在数据库中输入空值。此值可以是日期,然后变为空值

如何转换此选项以避免在选项Strict On下产生错误?

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

  • 在要调用的存储过程中,将日期输入参数设置为等于null,使其成为默认值为null(@terminate DATETIME=null)的可选字段
  • 这样,如果在过程调用中不包含该参数,则过程不会失败

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

  • 原因是运算符
    If(condition,executeAndReturnIfTrue,executeAndReturnIfFalse)
    希望
    true
    false
    表达式返回相同的类型。
    在本例中,如果结果为true,则返回
    DbNull
    type;如果结果为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
    }
    
    如注释中所述,使用
    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方法”


    所以答案是显而易见的,而且是错误的。我只需要将DBNull.Value封装在一个Ctype对象中

    CType(DBNull.Value, Object)
    

    然后代码就可以编译了。

    尝试在存储过程中为此参数设置默认的null值。
    DbNull
    Nothing
    不同。不知道什么是
    txtarningsteminated
    ,因为它有一个
    DateValue
    属性,但我怀疑它是否为null txtarningsteminated.DateValue是一个日期吗?很有趣,当大多数vb.net开发人员开始将
    选项Strict
    改为
    On
    -C#开发人员开始越来越多地使用
    动态
    关键字:)这花了我一点时间,但我已将所有AddWithValue更改为仅添加。我还做了一个程序来帮助改变。我不能在这里发布,因为它与这个问题无关。现在,回到Option Strict On changed。SQL语句非常小,将其转换为存储过程没有意义。在C#中,我可以使用null,它可以工作。我想知道为什么我不能在这里这样做?@Kayot
    AddWithValue
    可以给出问题:。(这是对您的程序选项严格遵守的赞誉。)只是有点迂腐,
    If()
    不是一个函数,而是一个操作符。
    CType(DBNull.Value, Object)