【问题标题】:How to deal with SqlDataReader null values in VB.net如何处理 VB.net 中的 SqlDataReader 空值
【发布时间】:2013-12-31 19:57:40
【问题描述】:

我有执行查询并返回结果的以下代码。但是,我环顾四周,发现了一些处理空值的示例,但出现错误:“不存在数据时读取的尝试无效。”我也收到错误消息:“从类型 '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

【问题讨论】:

  • 阅读我对您其他问题的回答。那里的代码已经有效地处理了这个问题。

标签: asp.net vb.net sqldatareader dbnull


【解决方案1】:

您已打开阅读器,但并未要求它实际阅读任何内容。

这一行之后:

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

【讨论】:

    【解决方案2】:

    我想提供另一个更高级的答案作为选项。许多类都可以像这样在 .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")
    

    【讨论】:

    • 非常好!也谢谢你!
    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    相关资源
    最近更新 更多