Vb.net 为什么这个返回的索引是越界异常

Vb.net 为什么这个返回的索引是越界异常,vb.net,Vb.net,当我到达读循环时,我得到一个索引越界错误。我认为这取决于读者顺序值,但我不确定为什么我会得到它 Private Function Create(Reader As SqlDataReader) As IEnumerable(Of MyObject) SetOrdinals(MyObjectReader) Dim MyObjects = New List(Of MyObject) While MyObjectReader.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
Private函数Create(读取器作为SqlDataReader)作为IEnumerable(MyObject的)
集合序号(MyObjectReader)
Dim MyObjects=新列表(MyObject)
而MyObjectReader.Read()
Dim Temp=新的MyObject()和{
.FirstValue=MyObjectReader.GetValue(整数的)(MyObjectReader(FirstValue_Ord)),
.SecondValue=If(MyObjectReader.GetValue(字符串的)(MyObjectReader(SecondValue_Ord)),String.Empty.Trim(),
.ThirdValue=If(MyObjectReader.GetValue(字符串的)(MyObjectReader(ThirdValue_Ord)),String.Empty).Trim(),
MyObject.Add(临时)
结束时
返回对象
端函数
私有子集合序号(MyObjectReader作为SqlDataReader)
FirstValueOrd=MyObjectReader.GetOrdinal(“FirstValue”)
SecondValue_Ord=MyObjectReader.getOrdinl(“SecondValue”)
ThirdValue_Ord=MyObjectReader.GetOrdinal(“ThirdValue”)
端接头
末级
公共模块扩展
函数GetValue(Of T)(rdr作为SqlDataReader,i作为整数)作为T
如果rdr.IsDBNull(i)那么
一无所获
如果结束
返回DirectCast(rdr.GetValue(i),T)
端函数
端模块

您应该将序号传递给
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
这是我的版本:)

Private函数Create(读取器作为SqlDataReader)作为IEnumerable(MyObject的)
将对象调整为新列表(MyObject)()
变暗序数作为新序数(读取器)
而reader.Read()
Dim Temp作为新的MyObject,具有
{
.FirstValue=reader.GetValuerDefault(整数的)(序数.FirstValue),
.SecondValue=reader.GetValueOrDefault(ordinals.SecondValue,”).Trim(),
.ThirdValue=reader.GetValueOrDefault(ordinals.ThirdValue,”).Trim()
}
对象。添加(临时)
结束时
返回对象
端函数
私有类序数
公共属性值为整数
公共属性值为整数
公共属性第三个值为整数
Public Sub New(读卡器作为SqlDataReader)
FirstValue=reader.GetOrdinal(nameOf(FirstValue))
SecondValue=reader.GetOrdinal(nameOf(SecondValue))
ThirdValue=reader.GetOrdinal(名称(ThirdValue))
端接头
末级
公共模块扩展
函数getValuerDefault(Of T)(读取器为SqlDataReader,序数为整数)为T
返回读取器.getValuerDefault(共T个)(序号,无)
端函数
函数getValuerDefault(Of T)(读取器为SqlDataReader,
序号为整数,
默认值为T)为T
尺寸值=读卡器(序号)
如果value=DbNull.value,则
返回默认值
如果结束
返回DirectCast(值,T)
端函数
端模块
因为扩展方法对已经提取的对象执行
DbNull.Value
检查,所以我们避免了从
SqlDataReader
中两次读取相同的值
SqlDataReader.IsDbNull(index)
在检查
DbNull
之前读取值

扩展方法有两个重载:
-如果值为
DbNull,则返回给定类型的默认值。vb.net中的value
Nothing
是类型的默认值。
-如果值为
DbNull,则将参数作为默认值返回。value
。传递默认值的可能性使创建新对象的行更短,可读性更强。我们去掉了内联
if
语句


名为
GetValue
的扩展方法具有“副作用”.By name此方法的使用者希望从
SqlDataReader
中获取值。因此,如果数据库查询返回
NULL
,他可以期望获取
DbNull.value
,但相反,对于字符串,他会获取
NULL
,对于整数,他会获取
0
。name
GetValueOrDefault
几乎没有更多信息,因此您不需要这样做进入方法以检查正在执行的操作。

很抱歉,我没有完全复制代码。实际代码使用Ordinal@Robert不同之处在于,参数应该只是序号-
FirstValue\u Ord
,而不是
MyObjectReader(FirstValue\u Ord)
。看起来你在重新发明轮子!
SqlDataReader
已经有了名为
GetString
GetInteger
等的方法。它们做的和你的
GetValue
方法做的一样。@ChrisDunaway很抱歉这么晚才回来。
GetString
等方法需要空检查,这就是我建议的原因d-中的
GetValue
扩展类似于
DataRow
的扩展方法。有更好的方法处理吗?
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