将类型为“DBNull”的值转换为类型“Date”无效。

6

我从以下VB.NET代码中仅在某些月份遇到此异常:

System.InvalidCastException: Conversion from type 'DBNull' to type 'Date' is not valid.

发生在这一行:
If CDate(dRow("CompleteDate")).ToString("d") = arrWeekYear(i, 1).ToString("d") Then

如果我理解正确的话,问题是我试图将一些NULL值与非NULL值的CompleteDate进行比较。
如何解决这个问题?对于某些日期,上面的代码运行得很好。 但是对于一些更近期的记录,它却不能正常运行。 但是,我能够从具有相同日期范围的T-SQL查询中获得输出,并且没有错误;它也运行得很快。 我还检查了这个T-SQL查询中的“Date_Completed”和“Review_Date”的NULL值,但无论如何,“CompleteDate”始终等于非NULL值。 所以我不明白这是怎么回事。
这是我的VB.NET查询:
            commandstring = "SELECT Batch_Records.Part_Number, Batch_Records.Lot_Number, Batch_Records.Date_Received, " & _
                "IsNull([Date_Completed], [Review_Date]) AS [CompleteDate], Batch_Records.Error, " & _
                "Batch_Records.[Group], Batch_Records.MFG, Batch_Records.MFG2, Batch_Records.QC, Batch_Records.QC2, " & _
                "QC_CODES.CODE_DESC, DATEADD(DD, 1 - DATEPART(DW, Batch_Records.Date_Received), Batch_Records.Date_Received) AS SundayDate " & _
                "FROM EXCEL.Batch_Records LEFT JOIN EXCEL.QC_CODES ON Batch_Records.Part_Number = QC_CODES.CODE_ID " & _
                "WHERE (Batch_Records.[Group]" & TheGroup & " AND Batch_Records.Date_Received > '" & FirstWeek & "' AND Batch_Records.Date_Received < dateadd(Day, 1, '" & LastWeek & "'))" & _
                   "ORDER BY Batch_Records.Date_Received"

当我在引起错误的那行代码上方添加此行时,我的报告在这些月份超时。那么该怎么办呢?
If Not dRow("CompleteDate") Is System.DBNull.Value Then

3
不要使用字符串拼接将值替换到查询中!千万不要这样做! - Joel Coehoorn
3
他是正确的,使用这段代码很容易受到 SQL 注入攻击! - David
在你的查询中,“EXCEL”是模式还是你正在某种方式下连接Excel表格?或者我们只处理SQL? - agent-j
CompleteDate列的数据类型是什么? - Chris Dunaway
给David点赞,因为他解释了为什么这很糟糕!!! - dooleyo
2个回答

8

在请求值之前,请使用dRow.IsNull("CompleteDate")检查是否为空。

或者,如果这是“不可能”的情况,请更改查询以永远不返回可以为null的行。


@Joel,我认为OP正在使用DataRow,因此正确的函数是IsNull。如果它是一个DataReader,你是对的,它应该是IsDBNull - agent-j
谢谢Joel,但是这并不起作用。 IsNull不是一个被VB.NET识别的函数。我尝试了IsDBNull,但是由于它不是正确的数据类型,所以导致编译错误。我唯一想到的使用IsDBNull的方法是像我上面解释的那样分开使用“if”语句。但是那样会超时。还有其他建议吗? - user371819
@OP,drow是什么?一个DataRow吗?这就是我说的方法:http://msdn.microsoft.com/en-us/library/3fwatee0.aspx - agent-j
如果你点击那个链接,你会发现实际上它是一个方法,但是你调用的方式不对。试试这个:Console.WriteLine(drow.IsNull("FirstName")) - agent-j
谢谢大家,我已经添加了这个但它仍然超时。我将数据集超时时间增加到12000,但它仍然超时。如果您有其他想法,请告诉我。(我也尝试选择前1000行,然后它完成了)。根据我的SQL查询结果,在这个日期范围内肯定有一些NULL日期值。 - user371819

0

我使用一个子函数(对于每种数据类型都不同)从Datareader中获取数据,使用索引而不是名称:

#If Access Then
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Friend Function GetDbStringValue(ByVal Dr As OleDbDataReader, ByVal nr As Integer) As String
#Else
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Friend Function GetDbStringValue(ByVal Dr As MySqlDataReader, ByVal nr As Integer) As String
#End If
    If IsDBNull(Dr.Item(nr)) Then
        Return ""
    Else
        Return Dr.GetString(nr).TrimEnd
    End If
End Function

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接