5

現在、Dynamic Linqを使用していくつかのテストを実行しようとしていますが、新しいため、問題が発生しています。

現在、SQLクエリによってデータベースに入力したDataTableオブジェクトが1つあります。次に、このDataTableで動的なlinqクエリを実行します。これは非論理的に思えるかもしれませんが、私の最終目標は、2つの異なるデータベースで埋められた2つの異なるDataTableで結合を実行できるようにすることです。そのことを念頭に置いて、より理にかなっていることを願っています。私は、その主要な問題を解決する前に、より単純な状況を理解し、それを少し実験しようとしています。

質問1は、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

これはうまくいくようです。最終的にどちらのフィールドを取得するかを動的に決定したいので、2つの文字列変数を使用しました。ですから、「x!Description」は私にとっては道のりではありません。ただし、ここでクエリにプロジェクションを追加したかったのです。つまり、いくつかの列を選択します。これは次のように機能するはずです。

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

(注:この特定の列にはタイプとしてそれがあるため、Select(Of String)を使用します。もちろん、これも最終的に動的に入力する必要があります)

ただし、これは実行時にInvalidCastExceptionで失敗します:「タイプ'WhereSelectEnumerableIterator1 2[System.Data.DataRow,System.String]' to type 'System.Collections.Generic.IEnumerable[System.Data.DataRow]'のオブジェクトをキャストできません。」私はここで何が起こっているのか本当に理解していません。DataRowを返したいので、何かがおかしいと思いますが、現時点では、たまたま文字列である1つのフィールドのみを選択します。誰かが私を説明/助けてもらえますか?

前もって感謝します!

OK、編集します。おそらく最初からもう少し情報を提供する必要があったので、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)ただし、タイプが、タイプの結果を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)があなたWhereSelect、より良い使用で使用するのかわかりません。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 に答える