【问题标题】:DataTable.Select with AND conditions doesn't give expected resultsDataTable.Select with AND 条件没有给出预期的结果
【发布时间】:2016-01-04 10:05:44
【问题描述】:

我正在尝试比较两个数据表,并且我正在使用 DataTable.Select 对两个相同的数据表进行一些测试:

Using DT_NewData As DataTable = DT_DBData.Copy
    For x As Short = 0 To DT_NewData.Rows.Count - 1
        Dim SelRows As DataRow() = DT_DBData.Select( _
            "Type='" & DT_NewData.Rows(x)("Type") & "'" & _
            " AND In_Date='" & DT_NewData.Rows(x)("In_Date") & "'" & _
            " AND Out_Date='" & DT_NewData.Rows(x)("Out_Date") & "'")
    Next

SelRows.Length 始终为 0。我的代码有什么问题?

【问题讨论】:

  • 你应该使用Option Strict On 然后它不会编译。您不能仅将字符串与 & 连接对象。我假设 In_DateOut_Date 是日期列。使用 Option Strict Off 时,它们会使用 ToString 自动转换为字符串。这不会返回 DataTable.Select 所需的日期的不变文化格式,而是返回您当前文化的格式。所以使用DT_NewData.Rows(x).Field(Of Date)("In_Date").ToString(CultureInfo.InvariantCulture)
  • @TimSchmelter 好的。我理解我的错误。无论如何,当字段为DBNull 时,您的建议将返回Invalid Cast Exception。你能推荐另一种方法吗?

标签: vb.net select datatable


【解决方案1】:

虽然表格的副本有点奇怪,但试试这个:

假设TypeString

Imports Microsoft.VisualBasic
Imports System.Linq

Module StartupModule

Sub Main()
    ' Declare the table.
    Dim originalDataTable As New DataTable

    ' Declare the table columns.
    With originalDataTable.Columns
        .Add("Type", GetType(String))
        .Add("InDate", GetType(DateTime))
        .Add("OutDate", GetType(DateTime))
    End With

    ' Delegate to add rows.
    Dim addRow As Action(Of String, DateTime?, DateTime?) = Sub(text, inDate, outDate)
    Dim newRow As DataRow = originalDataTable.NewRow()

    With newRow
        If (Not String.IsNullOrEmpty(text)) Then
            .SetField(Of String)("Type", text)
        End If

        If (inDate.HasValue) Then
            .SetField(Of DateTime?)("InDate", inDate.Value)
        End If

        If (outDate.HasValue) Then
            .SetField(Of DateTime?)("OutDate", outDate.Value)
        End If
    End With

    originalDataTable.Rows.Add (newRow)
End Sub

' Adding rows to the table.
addRow("type1", #2/2/2017#, Nothing)
addRow(Nothing, #1/25/2016#, Nothing)
addRow(Nothing, Nothing, #1/30/2016#)

' Copy the table
Dim copiedDataTable As DataTable = originalDataTable.Copy

' Loop through copied table rows.
For i As Integer = 0 To copiedDataTable.Rows.Count - 1
    Dim type As String = copiedDataTable.Rows(i).Field(Of String)("Type")
    Dim inDate As DateTime? = copiedDataTable.Rows(i).Field(Of DateTime?)("InDate")
    Dim outDate As DateTime? = copiedDataTable.Rows(i).Field(Of DateTime?)("OutDate")

    ' Using DataTable Select.
    Dim filter As String = String.Format("{0} {1} {2}",
        If(type Is Nothing, "( Type Is Null )", String.Format("( Type = '{0}' )", type)),
        If(Not inDate.HasValue, "And ( InDate Is Null )", String.Format("And ( InDate = '{0}' )", inDate.Value.ToString())),
        If(Not outDate.HasValue, "And ( OutDate Is Null )", String.Format("And ( OutDate = '{0}' )", outDate.Value.ToString())))

    Dim usingSelectRows As DataRow() = originalDataTable.Select(filter)
    Console.WriteLine("usingSelectRows.Count = {0}", usingSelectRows.Count)

    ' Using Linq.
    Dim typeSelector As Func(Of DataRow, Boolean) = Function(r)
    If (IsNothing(type)) Then
        Return IsNothing(r.Field(Of String)("Type"))
    Else
        Return r.Field(Of String)("Type") = type
    End If
End Function

    Dim inDateSelector As Func(Of DataRow, Boolean) = Function(r)
    If (Not inDate.HasValue) Then
        Return Not r.Field(Of DateTime?)("InDate").HasValue
    Else
        Return r.Field(Of DateTime?)("InDate").GetValueOrDefault.CompareTo(inDate.GetValueOrDefault) = 0
    End If
End Function

    Dim outDateSelector As Func(Of DataRow, Boolean) = Function(r)
    If (Not outDate.HasValue) Then
        Return Not r.Field(Of DateTime?)("OutDate").HasValue
    Else
        Return r.Field(Of DateTime?)("OutDate").GetValueOrDefault.CompareTo(outDate.GetValueOrDefault) = 0
    End If
End Function

    Dim usingLinqRows = From r In originalDataTable.AsEnumerable
                Where
                    (typeSelector(r)) AndAlso
                    (inDateSelector(r)) AndAlso
                    (outDateSelector(r))
                Select r

    Console.WriteLine("usingLinqRows.Count = {0}", usingLinqRows.Count)

    Console.WriteLine()
Next

    Console.ReadLine()
End Sub

End Module

始终使用DataRowField 扩展名来检索数据。

【讨论】:

  • 你测试了吗?还有DBNull 数据字段?在我的场景中SelRows.Length 是 0。
  • @genespos 我已经用一个完整的例子编辑了我的答案。
  • 感谢您的努力,但我不是专业人士,我正在尝试通过比较每个单元格(排序后)来解决
  • 没问题我的朋友。问题从数据表中的 Null 值开始。希望我的例子有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
  • 1970-01-01
  • 2019-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
相关资源
最近更新 更多