5

我目前正在尝试使用 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))

(注意:我使用 Select(Of String),因为这个特定的列有它作为类型。这当然应该最终也被动态填充)

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

提前致谢!

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

4

1 回答 1

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)在你的WhereandSelect中使用,更好地使用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将使您能够动态选择所需的字段。

要选择多个字段,您需要返回一组 Dictionary、ExpandoObjects 或 Tuples 或类似的东西。

例子:

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)
于 2012-08-21T11:59:23.647 回答