是否有一个干净利落的方法来处理带有Yields的空值?

时间:2016-11-18 17:18:36

标签: vb.net

While CommitReader.Read()
    Yield New Commit() With {
        .FirstValue = CommitReader.GetInt32(CommitReader.GetOrdinal("FirstValue")),
        .SecondValue = CommitReader.GetString(CommitReader.GetOrdinal("SecondValue")).Trim(),
        'Lots of values
End While

我知道我可以做这样的事情;然而,有24个属性,我想尽可能使这部分干净

While CommitReader.Read()
    new Commit (){
        Dim index As Integer = reader.GetOrdinal("FirstValue")
        If reader.IsDBNull(index) Then
            FirstValue = String.Empty
        Else
            FirstValue = reader(index)
        End If
        index = reader.GetOrdinal("SecondValue")
        If reader.IsDBNull(index) Then
            SecondValue = String.Empty
        Else
            SecondValue = reader(index)
        End If
    }
End While

有没有更好的方法来处理这类事情?我主要是一个C#开发人员,所以如果语法有点遗憾,我会在VB中使用它。

3 个答案:

答案 0 :(得分:2)

令人遗憾的是,SqlDataReader没有像DataRow那样的通用Field扩展方法,但你可以定义自己的扩展方法(必须在VB.NET的模块中)来帮助null检查,可能是这样的:

<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

使用类似这样的东西:

While CommitReader.Read()
    Yield New Commit() With {
        .FirstValue = CommitReader.GetValue(Of Integer?)(CommitReader.GetOrdinal("FirstValue")),
        .SecondValue = CommitReader.GetValue(Of String)(CommitReader.GetOrdinal("SecondValue")),
        'Lots of values
End While

我还没有对此进行全面测试,以确保它能够正确处理所有数据类型(可能值得一看DataRowExtensions.Field以了解它是如何做到的)。

请注意,您使用String.Empty作为&#34; null&#34;字符串的值,虽然这将使用Nothing / null(我还必须删除.Trim调用以避免NRE)。如果你想要空字符串,你可以使用(添加Trim):

.SecondValue = If(CommitReader.GetValue(Of String)(CommitReader.GetOrdinal("SecondValue")), String.Empty).Trim()

您可能还希望将GetOrdinal调用移出循环以提高性能。

答案 1 :(得分:1)

显然,您的代码if ... else ...条件会重复 所以你可以用另一种方法提取它。

对于您的情况,通用扩展方法似乎是很好的候选者。

Public Module Extensions    
    <Extension>  
    Public Function GetValueOrDefault(Of T)(originalValue As object, 
                                            defaultValue As T) As T
        If originalValue = DbNull.Value Then
            Return defaultValue
        End If

        return DirectCast(originalValue, T)
    End Function
End Module

然后使用它:

While CommitReader.Read() = True
    Dim temp = new Commit With
    {
        Dim index As Integer = reader.GetOrdinal("FirstValue")
        FirstValue = reader(index).GetValueOrDefault(String.Empty)

        Dim index As Integer = reader.GetOrdinal("SecondValue")
        FirstValue = reader(index).GetValueOrDefault(String.Empty)       
    }
End While

您可以创建另一个重载,如果它是DbNull

,则返回给定类型的“默认”值
<Extension>  
Public Function GetValueOrDefault(Of T)(originalValue As object) As T
    Return originalValue.GetValueOrDefault(Nothing)
End Function
vb.net中的

Nothing是默认值,对于null,引用类型为Integer,例如0

要使用此重载,您需要明确提供类型参数

While CommitReader.Read() = True
    Dim temp = new Commit With
    {
        Dim index As Integer = reader.GetOrdinal("FirstValue")
        FirstValue = reader(index).GetValueOrDefault(Of String)()

        Dim index As Integer = reader.GetOrdinal("SecondValue")
        FirstValue = reader(index).GetValueOrDefault(Of String)()       
    }
End While

请注意,您的解决方案执行reader两次,检查是否为空并且读取值。这可能会导致“微小”的性能问题。

因此,在上面的扩展方法中,我们只读取一次值,然后检查DbNull的值。

答案 2 :(得分:0)

如果将字符串与Null连接,则会得到字符串:

FirstValue = reader(index) & ""

有点“不专业”,但如果您正在做的就是将可能的Null转换为空字符串,则会节省大量编码时间。但是很容易忘记,因此可能会出现以后的数据相关错误。