【问题标题】:Query a DataTable via Dynamic LINQ通过动态 LINQ 查询数据表
【发布时间】:2020-07-19 10:23:47
【问题描述】:

我有一个 DataTable,喜欢通过 Dynamic LINQ 进行查询。

Imports System.Linq.Dynamic.Core
...
Dim Values as DataTable
...

当我简单地选择一个特定的列(名为“年龄”)时,​​例如:

    Dim result = Values.AsEnumerable.AsQueryable.Select("age")

但现在我想通过 where 子句过滤 DataTable,但它不起作用,或者我不知道如何正确实现:

Dim result = Values.AsEnumerable.AsQueryable.Where("age > 60")

我得到了:

"二元运算符 GreaterThan 没有为 System.Object 和 System.Int32"

好的,我在一定程度上理解了错误消息,但我不知道如何相应地更改我的代码。

【问题讨论】:

  • 我不会将此作为答案发布,因为我还没有测试过它,但事实上从DataRow 获取值总是返回一个对象引用,你大概必须转换/转换为实际数据的类型。在这种情况下,我的首选是"CInt(age)""Convert.ToInt32(age)""DirectCast(age, Integer)"
  • 尝试创建一个强类型数据集/数据表。它们也可以在不需要 AsXXXable 的情况下查询
  • @jmcilhinney 非常感谢这个最初的想法。 "Convert.ToInt32(age)" 有效。

标签: vb.net linq datatable


【解决方案1】:

这是一个 Linq to DataTable 的例子。 LoadCoffeeTable 返回一个数据表。类型和名称都是数据表中的字符串字段。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim dt = LoadCoffeeTable()

    Dim result = From r As DataRow In dt.AsEnumerable
                 Where r("Type").ToString() = "Regular"
                 Select r("Name")

    For Each r In result
        Debug.Print(r.ToString)
    Next
End Sub

【讨论】:

  • @CaiusJard Dim ColumnToTest = "Type" Dim TestValue = "Regular" Dim ReturnColumn = "Name" 然后使用 Linq 查询中的变量使其动态化?我将编辑我的答案,否则请赐教。
  • 这是“普通 linq”,动态的意思是开发人员可以将任何他们喜欢的东西扔进去,但静态的意思是,一旦程序被编译,查询在哪里查找并返回在其选择中是“烘焙”的。动态是将查询的条件表示为在运行时解析和运行的字符串,而不是编译时。本质上,您的查询将始终只查询咖啡类型并返回名称。作为动态的,它可能看起来像.Where("type = ""Regular"""),但关键是该字符串可能是像.Where(queryString) 这样的变量 - “所以可以挖掘”..
  • ..您可能会说,“看:` Where r(whatColumnStr).ToString() = whatValueStr` 但有几件事 - 这修复了使用字符串进行的比较,这不是真的动态的,因为它只比较一个列的事实是在编译时烘焙的。动态 LINQ 变量很容易是 "type = ""Regular" && size > 2" 的字符串,因此它是真正动态的,即“在运行时评估,而不是编译时”
【解决方案2】:

正如 cmets 中所提到的,如果您使用强类型数据表,它会大大改善您的生活。这些是由设计者生成的数据表,具有命名、类型化的属性,而不是一切都是对象,通过字符串访问

我们通过使用“添加新项目”将 DataSet 添加到我们的项目中来制作强类型数据表:

你可以忽略我说的 C# - 这正是我正在为其他一些 qustion 工作的项目所使用的。这两种语言在底层是相同的。在您的 VB 项目的数据标题下查找您的

当你添加它时,你会得到一个表面,右键单击它并Add >> DataTable。右键单击数据表和Add >> Column,提供列名称和属性。对于学生和班级,我通过链接数据库并将数据库表放到设计器中来生成它们,所以我没有手动创建它们,但你可以。如果您正在使用数据库,请右键单击表面并添加 >> TableAdapter,配置连接和查询,您将获得一个模仿您的数据库表的数据表。如果您没有数据库,只需手动创建表和列 - 我是使用“NotFromDb”表完成的;对于那个我点击并添加数据表/列。即使您没有数据库并且“手动”创建数据表,它仍然会比编写 Dim dt as new DataTabledt.Columns.Add("Age", ...) 等语句更快、更容易和更好

所以你最终会得到这样的东西:

就是这样;您的强类型数据表已准备就绪!与常规数据表相比,它们更易于使用。例如,要递增 NotfromDB 中的所有 BlahInt,代码如下所示:

For Each r in notFromDb
  r.BlahInt += 1
Next r

在弱类型数据表中也是如此:

For Each r as DataRow in notFromDb.Rows
  r("BlhaInt") = DirectCast(r("BlahInt"), Integer) + 1
Next r

您可以看到我在 BlhaInt 中打错了字,而 Intellisense 不会帮助我,因为它是一个字符串,而不是完整的属性名称。代码也更难阅读,因为一切都是对象,由字符串访问,必须强制转换以使其有用

总而言之,简单的数据表很麻烦,我很少使用它们,因为强类型数据表很容易创建并且使用起来更好


现在,关于动态的要点:

我的数据库中有这些值(这是:

这只是测试数据,但为我们提供了一些可以使用的东西。我们将为 ClassID > 5 进行动态处理

这是我的 VS 在执行动态后在调试器中停止的截图:

C# 中的this 与 VB 中的 me 相同。如前所述,这是 C#,因为它是我所使用的;看看schoolDB.Where,它与VB 中的相同。 schoolDS 是我的 Students 强类型数据表所在的数据集,因此数据表名称前有 schoolDS.

我已经将运算结果赋值给dt变量,C#var就像VB的Dim

所以你可以看到......它只是工作,它比使用弱类型数据表和拥有所有 AsEnumerable AsQueryable 等等更简单和更干净

【讨论】:

  • 非常感谢 Caius,真的是关于强类型数据集的一个伟大而全面的答案。当我从另一个对象获得DataTable 时(实现了一个 toDataTable 方法),我检索了这个无类型的表单。我想我可以自己将ForEach 的数据转换为 DataTable,但我担心它会更慢。但我会努力的。
  • 一个 ST 数据表最终仍然是一个数据表,并且仍然可以被只理解弱类型数据表的东西使用。如果您的 ST DT 具有属性 NameAgeAddress,那么它可以交给只知道如何访问它的东西,例如Rows[0]["Name"]Rows[0]["Age"]Rows[0]["Address"]。因此,如果您可以将列命名为与通过字符串访问的完全相同,然后将 STDT 提供给其他设备以填充数据,它就可以工作。请注意,如果其他设备创建弱类型的 DT 并将其提供给您的那么就如你所说..你会
  • 必须从中复制数据。看看Merge - 如果您将 STDT 设置为与设备返回的 WDT 具有相同的架构,那么您可能可以将它们与一个衬里合并。为了提供更多建议,我们确实需要您在兔子洞中走几步,并展示一些您以前没有的代码(为什么您首先拥有这个 Values 数据表)。可能是整个 ToDataTable() 是间接的,可以去掉,可以动态 Linq 原始源
  • Values 来自一个用于访问 SPSS 文件的 dll(用于数据分析的软件;nuget.org/packages/SPSS.NET)。 Data = Spss.SpssDataDocument.Open(file, Spss.SpssFileAccess.Read) 然后Values = Data.Cases.ToDataTable
  • 那么Data.Cases 可以以某种LINQy 方式进行查询吗?或者组件的代码是否可用于提供修改后的版本,例如Data.Cases.FillDataTable(dtSuppliedByDirk) ?
【解决方案3】:

欢迎堆栈溢出!!!

尝试以下几点:

Include System.Linq.Dynamic

where

select

query

【讨论】:

  • 这个答案太模糊了。答案必须针对所提出的具体问题,而不仅仅是给某个地方自己寻找答案的地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
  • 2016-10-16
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多