【问题标题】:How to Select Rows in a Datatable?如何选择数据表中的行?
【发布时间】:2021-01-30 06:25:27
【问题描述】:

如何使用变量 Itmnmbr 而不是硬编码其值 'i-2051'

Dim fr() As DataRow
Dim Itmnmbr As string = "i-2051"
fr = dt.Select("item = 'i-2051'")

【问题讨论】:

    标签: vb.net datatable


    【解决方案1】:

    最直接的方法是使用Interpolated String,可从 Visual Studio 2015、VB.Net 14 获得:

    Dim Itmnmbr As string = "i-2051"
    fr = dt.Select($"item = '{Itmnmbr}'")
    

    作为建议,让我们更改变量/字段的名称,以便更容易阅读并了解这些对象的用途。例如:

    Dim dt as New DataTable()
    '[...]
    Dim itemNunmber As string = "i-2051"
    Dim filteredRows As DataRow() = dt.Select(...)
    

    itemNunmberItmnmbr 更易于阅读,filteredRowsfr 更明确。在这种情况下,有一些 convection 是大多数人习惯的,例如 dt 用于 DataTable,ds 用于 DataSet 等。最好确保当您在一段时间后阅读您的代码时,您不会对自己生气:)

    注意,Interpolated String 和String.Format() 格式的字符串是一样的,所以这两者其实是一回事:

    Dim filteredRows As DataRow() = dt.Select($"item = '{itemNumber}'")
    Dim filteredRows As DataRow() = dt.Select(String.Format("item = '{0}'", itemNumber))
    

    设置Option Infer On(应该是On),使用local type inference,你可以写:

    Dim filteredRows = dt.Select($"item = '{itemNumber}'")
    

    并让编译器推断类型。在 Visual Studio 中,如果您将鼠标指针移到变量上,它会告诉您这是什么类型。

    如果您需要更多动态选择,您还有其他选择。
    DataTableExtensions(需要对 System.Data.DataSetExtensions 程序集的项目引用 - 通常已与 System.Data 一起链接),让您使用 AsEnumerable() 方法。

    LINQ to Objects 风格:
    这里,使用默认的字符串Comparer

    Dim filteredRows = 
        dt.AsEnumerable().Where(Function(dr) dr("item").ToString().Equals(itemNumber))
    

    LINQ to SQL 风格:
    在这里,使用InvariantCulture 进行比较。

    Dim filteredRows =
        From row In dt.AsEnumerable()
        Where row.Field(Of String)("item").Equals(itemNumber, StringComparison.InvariantCulture)
        Select row
    

    另请参阅:StringComparisonBest practices for comparing strings in .NET

    最后这两个方法不返回 DataRow 对象引用的数组,而是一个 EnumerableRowCollection。优点是(当您可以使用它时)集合仅在您实际使用它时返回(执行被延迟)。
    如果使用得当,它可以提高代码的性能。试试看。

    除了DataTable.Select(),您还可以使用其DefaultView.RowFilter 属性过滤您的DataTable。

    dt.DefaultView.RowFilter = $"item = '{itemNumber}'"
    ' You can save the filter to restore it later, if needed
    Dim previousFilter = dt.DefaultView.RowFilter
    

    当您呈现 DataTable 的行时,仅显示满足过滤器定义的条件的行(例如,在排序的 DataGrid 中)。

    如前所述,您在此处使用引用。 DataTable.Select() 返回的行集合包含对 DataTable 中行的引用。

    例如,如果您考虑 Collection 和过滤后的 DataTable:

    Dim filteredRows = dt.Select($"item = '{itemNumber}'")
    dt.DefaultView.RowFilter = $"item = '{itemNumber}'"
    

    假设filteredRows 包含一个行。然后应用过滤器。
    如果你现在改变filteredRows(0)("item")的值:

    filteredRows(0)("item") = "Some other value"
    

    当您在 UI 中显示 DataTable 时,将不会显示任何行,因为过滤器处于活动状态,并且现在没有任何行符合过滤器的条件:设置 filteredRows(0)("item") 已更改它所引用的行的值。

    要删除过滤器,请将其设置为 string.Empty:

     dt.DefaultView.RowFilter = Sting.Empty
    

    要恢复之前保存的过滤器:

     dt.DefaultView.RowFilter = previousFilter
    

    【讨论】:

    • 当我使用Dim previousFilter = dt.DefaultView.RowFilter = $"item = '{itemNumber}'" 时,它不会改变 DataGridView 中的显示。 dt.DefaultView.RowFilter = $"item = '{itemNumber}'" 过滤数据。 previousFilter 是一个 Boolean 和 ,似乎第二个 = 是一个比较,而不是一个赋值。我在哪里偏离轨道?
    • @Mary 是的,这是一个太快的复制/粘贴(它在 C# 中进行了代码测试,返回值是一个字符串,但无论如何这不是设置过滤器的方法)。我以为我改变了它,而不是我只修改并删掉了最后一行,那里有相同的双重分配。感谢您的关注。已编辑。
    猜你喜欢
    • 2018-05-06
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 2023-03-14
    • 2014-07-29
    • 2017-04-20
    相关资源
    最近更新 更多