如何在VB.net中处理SqlDataReader null值

时间:2013-12-31 19:57:41

标签: asp.net vb.net sqldatareader dbnull

我有以下代码执行查询并返回结果。但是,我环顾四周并找到一些例子来处理空值,但是我收到一个错误:“当没有数据存在时无效的读取尝试。”我也收到错误:“从'DBNull'类型转换为'Decimal'类型无效。”

有人可以帮我解决这段代码,以防止空值崩溃我的程序吗?

Private Sub EFFICIENCY_STACKRANK_YTD(ByVal EMPLOYEE As String)

    Dim queryString As String = "SELECT " & _
    " (SELECT CAST(SUM(TARGET_SECONDS) AS DECIMAL)/ CAST(SUM(ROUTE_SECONDS) AS DECIMAL) FROM dbo.APE_BUSDRIVER_MAIN WITH(NOLOCK) WHERE APE_AREA_OBJID = " & lblAreaOBJID.Text & " AND EMPLOYEE_NAME = '" & EMPLOYEE & "' AND YEAR_TIME = '" & cbYear.Text & "' AND ACTIVE = 1) AS RESULT1" & _
    " FROM dbo.APE_BUSDRIVER_MAIN "


    Using connection As New SqlConnection(SQLConnectionStr)
        Dim command As New SqlCommand(queryString, connection)
        connection.Open()
        Dim reader As SqlDataReader = command.ExecuteReader()

        If reader.Read Then
            RESULT1 = reader("RESULT1")
        Else
            RESULT1 = 0
        End If

    End Using
End Sub

2 个答案:

答案 0 :(得分:9)

我想提供另一个更高级的答案作为选项。许多类都可以在.NET中进行扩展。

如果您在应用程序中定期执行“Is NULL”检查,则可以选择扩展DataReader类一次,以便在应用程序的任何位置都可以使用其他功能。下面是一个在数据读取器类上创建名为“ReadNullAsString()”的扩展的示例。这使得一个函数在遇到DbNull时总是返回String.Empty。

第1部分,如果应用程序是网站,则将此模块代码放在App_Code中的新类文件中,否则放置在您喜欢的位置。有两个重载,一个用于字段的序数位置(也就是索引),另一个用于字段的ColumnName。

Public Module DataReaderExtensions

    ''' <summary>
    ''' Reads fieldName from Data Reader. If fieldName is DbNull, returns String.Empty.
    ''' </summary>
    ''' <returns>Safely returns a string. No need to check for DbNull.</returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ReadNullAsEmptyString(ByVal reader As IDataReader, ByVal fieldName As String) As String
        If IsDBNull(reader(fieldName)) Then
            Return String.Empty
        Else
            Return reader(fieldName)
        End If
        Return False
    End Function

    ''' <summary>
    ''' Reads fieldOrdinal from Data Reader. If fieldOrdinal is DbNull, returns String.Empty.
    ''' </summary>
    ''' <returns>Safely returns a string. No need to check for DbNull.</returns>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ReadString(ByVal reader As IDataReader, ByVal fieldOrdinal As Integer) As String
        If IsDBNull(reader(fieldOrdinal)) Then
            Return ""
        Else
            Return reader(fieldOrdinal)
        End If
        Return False
    End Function

End Module

步骤2,像这样调用新扩展名:

' no need to check for DbNull now, this functionality is encapsulated in the extension module.
RESULT1 = reader.ReadNullAsEmptyString(index)
'or
RESULT1 = reader.ReadNullAsEmptyString("RESULT1")

答案 1 :(得分:8)

您已经打开了阅读器,但没有要求它实际阅读任何内容。

这一行之后:

Dim reader As SqlDataReader = command.ExecuteReader()

添加

If reader.Read() Then

并将结果读数包装到此if语句中,即

If reader.Read() Then
    Dim index As Integer = reader.GetOrdinal("RESULT1")
    If reader.IsDBNull(index) Then
        RESULT1 = String.Empty
    Else
        RESULT1 = reader(index)
    End If
End If

请注意,这是有效的,因为您的SQL应该只返回一条记录。如果您正在读取多个记录,则需要在循环中调用Read语句,直到没有更多记录为止。

Do While reader.Read()

Loop