为什么这个返回的索引超出了绑定异常

时间:2016-11-18 22:03:58

标签: vb.net

当我进入Read循环时,我得到一个索引越界错误。我认为这取决于读者的序数价值,但我不确定为什么我会得到它。

Private Function Create(Reader As SqlDataReader) As IEnumerable(Of MyObject)

        SetOrdinals(MyObjectReader)
        Dim MyObjects = New List(Of MyObject)

        While MyObjectReader.Read()
            Dim Temp = New MyObject() With {
                .FirstValue = MyObjectReader.GetValue(Of Integer)(MyObjectReader(FirstValue_Ord)),
                .SecondValue = If(MyObjectReader.GetValue(Of String)(MyObjectReader(SecondValue_Ord)), String.Empty).Trim(),
                .ThirdValue = If(MyObjectReader.GetValue(Of String)(MyObjectReader(ThirdValue_Ord)), String.Empty).Trim(),                
            MyObjects.Add(Temp)
        End While
        Return MyObjects

    End Function

    Private Sub SetOrdinals(MyObjectReader As SqlDataReader)
        FirstValueOrd = MyObjectReader.GetOrdinal("FirstValue")
        SecondValue_Ord = MyObjectReader.GetOrdinal("SecondValue")
        ThirdValue_Ord = MyObjectReader.GetOrdinal("ThirdValue")        
    End Sub

End Class


Public Module Extensions

    <Extension>
    Function GetValue(Of T)(rdr As SqlDataReader, i As Integer) As T
        If rdr.IsDBNull(i) Then
            Return Nothing
        End If
        Return DirectCast(rdr.GetValue(i), T)
    End Function
End Module

2 个答案:

答案 0 :(得分:2)

您应该将序数传递给GetValue来电:

While MyObjectReader.Read()
    Dim Temp = New MyObject() With {
        .FirstValue = MyObjectReader.GetValue(Of Integer)(FirstValue_Ord),
        .SecondValue = If(MyObjectReader.GetValue(Of String)(SecondValue_Ord), String.Empty).Trim(),
        .ThirdValue = If(MyObjectReader.GetValue(Of String)(ThirdValue_Ord), String.Empty).Trim()
    }
    MyObjects.Add(Temp)
End While

答案 1 :(得分:0)

这是我的版本:)

Private Function Create(reader As SqlDataReader) As IEnumerable(Of MyObject)
    Dim objects As New List(Of MyObject)()        

    Dim ordinals As New Ordinals(reader)
    While reader.Read()
        Dim Temp As New MyObject With 
        {
            .FirstValue = reader.GetValueOrDefault(Of Integer)(ordinals.FirstValue),
            .SecondValue = reader.GetValueOrDefault(ordinals.SecondValue, "").Trim(),
            .ThirdValue = reader.GetValueOrDefault(ordinals.ThirdValue, "").Trim()
        }

        objects.Add(Temp)
    End While
    Return MyObjects

End Function

Private Class Ordinals
    Public Property FirstValue As Integer
    Public Property SecondValue As Integer
    Public Property ThirdValue As Integer

    Public Sub New(reader As SqlDataReader)
        FirstValue = reader.GetOrdinal(nameOf(FirstValue))
        SecondValue = reader.GetOrdinal(nameOf(SecondValue))
        ThirdValue = reader.GetOrdinal(nameOf(ThirdValue))
    End Sub
End Class


Public Module Extensions
    <Extension>
    Function GetValueOrDefault(Of T)(reader As SqlDataReader, ordinal As Integer) As T
        Return reader.GetValueOrDefault(Of T)(ordinal, Nothing)
    End Function

    <Extension>
    Function GetValueOrDefault(Of T)(reader As SqlDataReader, 
                                     ordinal As Integer, 
                                     defaultValue As T) As T
        Dim value = reader(ordinal)
        If value = DbNull.Value Then
            Return defaultValue
        End If
        Return DirectCast(value, T)
    End Function
End Module

因为扩展方法针对已经提取的对象执行DbNull.Value检查,所以我们摆脱了从SqlDataReader两次读取相同值。 SqlDataReader.IsDbNull(index)在检查DbNull之前读取值。

扩展方法有两个重载:
  - 如果值为DbNull.Value,则返回给定类型的默认值。 vb.net中的Nothing是类型的默认值   - 如果值为DbNull.Value,则需要返回默认值参数。可能性传递默认值使得创建新对象的行更短且更易读。我们摆脱了内联if声明。

您的名为GetValue的扩展程序有&#34;副作用&#34;。按名称,此方法的消费者希望从SqlDataReader获得价值。因此,如果数据库查询返回DbNull.Value,他可以期望获得NULL,而是获得null表示字符串或0表示整数。名称GetValueOrDefault的出价较少,因此您无需进入内部方法来查看正在执行的操作。