动态Linq查询 - 如何构建select子句?

时间:2012-08-21 10:11:35

标签: vb.net linq dynamic vb.net-2010

我正在尝试使用Dynamic Linq进行一些测试,但是对它来说是新的,我遇到了麻烦。

目前我有一个DataTable对象,我已经通过SQL查询填充到数据库。现在我想在这个DataTable上执行动态linq查询。这可能看起来不合逻辑,但我的最终目标是能够在由两个不同数据库填充的两个不同的DataTable上执行连接,所以考虑到这一点,我希望它更有意义。 在我继续解决这个主要问题之前,我正试图了解一个更简单的情况并进行一些实验。

问题一是我不完全确定IQueryable(Of T)和IEnumerable(Of T)之间的选择。我理解的方式是,如果你在内存中做所有事情,你选择IEnumerable。我认为那适合我的情况,对吗?但是,当我查看更改IQuerbyable中的IEnumerable时(在下面的代码片段中),我惊讶地发现“x.Item(Fieldname)”不起作用!?我错过了什么?它给出的错误是:“后期绑定操作无法转换为表达式树”。

无论如何,我们来看看吧。我已经完成了部分工作:

    Dim desc As String = "Description"
    Dim status As String = "Status"

    Dim query As IEnumerable(Of DataRow) = From x In tab.AsEnumerable()
    query = query.Where(Function(x As Object) x.Item(status) < 100)

    For Each row As DataRow In query.ToList()
    'Do something
    Next row

这似乎工作正常。我使用了两个字符串变量,因为最后我想动态决定采用哪个字段。所以,“x!描述”不适合我。但是,现在我想在查询中添加一个投影,即选择一些列。我的期望是这应该是这样的:

query = query.Select(Of String)(Function(x As Object) x.Item(desc))

(N.B。:我使用Select(Of String),因为这个特定的列具有类型。这当然也应该动态填充)

但是,在运行时对InvalidCastException失败:“无法转换类型为'WhereSelectEnumerableIterator 2[System.Data.DataRow,System.String]' to type 'System.Collections.Generic.IEnumerable 1 [System.Data.DataRow]'的对象。”我真的不明白这里发生了什么;我猜错了,因为我想返回DataRow,但目前只选择一个字段,恰好是一个字符串。谁能解释/帮助我?

提前致谢!

好的,编辑,因为我应该从头开始提供更多信息: 我可以有一个可变数量的where-或select-子句。我的想法是我可以通过循环包含此信息的列表来动态添加这些。所以我认为我需要IEnumerable提供的.Where()和.Select()函数。

1 个答案:

答案 0 :(得分:3)

您在以下行中声明query类型为IEnumerable(Of DataRow)

Dim query As IEnumerable(Of DataRow) = From x In tab.AsEnumerable()

现在,您想要使用IEnumerable(Of String)创建Select,这很好。

但是您尝试将IEnumerable(Of String)类型的结果设置为queryIEnumerable(Of DataRow)类型。

query = query.Select(Of String)(Function(x As Object) x.Item(desc))

由于IEnumerable(Of String)无法转换为IEnumerable(Of DataRow),反之亦然,因此您获得了InvalidCastException


此外,我不知道您在Function(x As Object)Where中使用Select的原因,更好地使用Function(row As DataRow),因为您已经知道自己正在使用DataRow Dim desc As String = "Description" Dim status As String = "Status" Dim columnToUse = status Dim query = From x In tab.AsEnumerable() Where x.Item(status) < 100 Select x(columnToUse) For Each item as String In query.ToList() 'Do something Next

此外,您的代码可以像这样重写:

columnToUse

更改Dim columnToUse = new String() {desc, status} ' select columns dynamically Dim query = tab.AsEnumerable().Where(Function(row) row.Item(status) < 100) ' Selecting dynamically Dim result1 = query.Select(function(row) columnToUse.ToDictionary(function(c) c, function(c) row(c))) Dim result2 = query.Select(Function(row) Dim exp As IDictionary(Of String, Object) = new ExpandoObject() For Each column in columnToUse exp(column) = row(column) Next return exp End Function) 可让您动态选择所需的字段。

要选择多个字段,您需要返回Dictionarys,ExpandoObjects或Tuples等集合。

示例:

{{1}}
相关问题