使 DataTable 的 Select 和 ToArray 具有 DBNull 感知能力
Making Select and ToArray for DataTable DBNull-aware
从 DataTable 中提取数据时抛出异常“对象无法从 DBNull 转换为其他类型”。显然下面的语法不是“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 + 2, 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
从 DataTable 中提取数据时抛出异常“对象无法从 DBNull 转换为其他类型”。显然下面的语法不是“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 + 2, 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