【问题标题】:Making Select and ToArray for DataTable DBNull-aware为 DataTable DBNull-aware 制作 Select 和 ToArray
【发布时间】:2021-08-19 19:44:27
【问题描述】:

从 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 的行的双精度数组。

【问题讨论】:

  • 您希望发生什么?接受的答案将忽略这些记录,但还有其他选项,例如转换为零。始终提供完整而清晰的解释。
  • @jmcilhinney 你在上下文中是对的(我认为同样的事情),但有时人们必须知道 SO 的用户并不是全职致力于这个网站来做出明确和完整的答案(对于也存在MS指南)然后他们尝试根据他们必须致力于明确和全面响应的时间来提供帮助(不幸的是)。保持安全。
  • @G3nt_M3caj,我并没有批评你的回答,就其本身而言。我批评这个问题没有提供足够的信息,无法在不做假设的情况下提供答案。
  • 答案有效。我从来没有将 null 设置为零,因为这就像说没有任何东西等于零,而没有测量值。告诉学生危险的事情,因为缺失到零会导致特征值的频率直方图中出现零尖峰 - 称为间歇性(湍流)。通过用均值、中值、最小值、最大值替换空值的热甲板插补是选项,但您不知道空值是否完全随机丢失、随机丢失或非随机丢失,因此插补可能存在偏差。

标签: vb.net exception select datatable toarray


【解决方案1】:

如果我很理解你需要这样的东西 在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

【讨论】:

  • 这就像一个魅力,是的,有很多实例我需要获取没有任何空值的多特征实值矩阵。
  • (参见修改后的 OP)-我实际上是从一个我知道是双列名称的字符串数组开始。那么有没有办法将所有请求的列名连接到一个查询字符串中,然后将其注入到 Select 命令中?
  • 是的,你可以做一些技巧(例如:使用 Func(Of List(Of String)) 而不是指定每个字段。这里我没有在这台机器上安装 VS,但我明天会展示一些东西
  • @wrstks ,更新,忽略填充DataTable的部分
  • 它有效,但是在检查数组中的行值时,每一行都列为“内存中查询”,所以我看不到数字。有没有办法杀死它并将内存查询转换为双打? (也许这就是你的最后一个循环所做的,但是,我试图避免在 ToArray 调用之后循环)。
猜你喜欢
  • 2014-04-27
  • 1970-01-01
  • 2012-04-13
  • 2018-12-16
  • 2015-04-08
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多