为 DataTable DBNull-aware 做 Select 和 ToArray

问题描述

从 DataTable 中提取数据时抛出异常“Object cannot be cast from dbnull to other types”。显然,下面的语法不是“dbnull 感知”。如果在转换过程中发现 dbnull,有没有办法防止抛出此异常?

 Dim arrayOfDoubles()() As Double = DT.AsEnumerable().Select(Function(x) {Convert.Todouble(x("Age")),Convert.Todouble(x("Weight")),Convert.Todouble(x("Location"))}).ToArray()

此外,我实际上是从我知道是双精度的列名的字符串数组开始的。那么有没有办法将所有请求的列名连接到一个查询字符串中,然后将其注入到 Select 语句中?以这种方式,我将只获得所有列都不是 dbnull 的行的双精度数组。

解决方法

如果我明白你需要这样的东西 在 Where 子句中,您可以测试您的字段是否有 DbNull 值。

  Dim arrayOfDoubles()() As Double = DT.AsEnumerable().
            Where(Function(f) f("Age") IsNot DBNull.Value AndAlso f("Weight") IsNot DBNull.Value).
            Select(Function(x) {Convert.ToDouble(x("Age")),Convert.ToDouble(x("Weight")),Convert.ToDouble(x("Location"))}).ToArray()

无需在每个子句(在 where 和 select)中进行具体说明,您可以使用一些集中的“技巧”来简化您的代码,如下所示:

    Dim DT As DataTable = New DataTable

    DT.Columns.Add("Age",GetType(Double))
    DT.Columns.Add("Weight",GetType(Double))
    DT.Columns.Add("Location",GetType(Double))
    DT.Columns.Add("Moves",GetType(Double))

    For i As Integer = 0 To 10
        Dim dr As DataRow = DT.NewRow
        If i Mod 2 = 0 Then
            dr.ItemArray = {i,DBNull.Value,i + 2,DBNull.Value}
        Else
            dr.ItemArray = {i,i + 1,i + 3}
        End If

        DT.Rows.Add(dr)
    Next


    '============================================================================
    Dim flds As List(Of String) = {"Age","Weight","Location","Moves"}.ToList
    Dim arrayOfDoubles()() As Double = DT.AsEnumerable().
    Where(Function(f) flds.Where(Function(el) f(el) IsNot DBNull.Value).Count = flds.Count).
    Select(Function(x) flds.Select(Function(el) Convert.ToDouble(x(el))).ToArray).ToArray
    '====================================================================================

    For Each el In arrayOfDoubles
        Debug.Print("Age:      " & el(flds.IndexOf("Age")).ToString)
        Debug.Print("Weight:   " & el(flds.IndexOf("Weight")).ToString)
        Debug.Print("Location: " & el(flds.IndexOf("Location")).ToString)
        Debug.Print("Location: " & el(flds.IndexOf("Moves")).ToString)
    Next

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...