我正在尝试使用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()函数。
答案 0 :(得分:3)
您在以下行中声明query
类型为IEnumerable(Of DataRow)
:
Dim query As IEnumerable(Of DataRow) = From x In tab.AsEnumerable()
现在,您想要使用IEnumerable(Of String)
创建Select
,这很好。
但是您尝试将IEnumerable(Of String)
类型的结果设置为query
,IEnumerable(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}}