1

現在、一連のデータベース結果セットのラッパー オブジェクトを作成しています。そうしているうちに、LINQおよびLambda式でクエリを実行するときに問題があることに気付きました。具体的には、ラムダ内でメソッドを呼び出すと、常に結果セットが空になり、フィルターしようとしているメソッドが実際に起動されることはありません。コードは次のとおりです。

' Query and filter container results 
Public Function [Filter](pFilter As IFilter(Of T)) As System.Linq.IQueryable(Of T)
    ' THIS YIELDS AN EMPTY SET EVEN WHEN pFilter.Test(o) ALWAYS RETURNS TRUE
    Dim lResult As System.Linq.IQueryable(Of T) = mTable.Where(Function(o As T) pFilter.Test(o))

    Return lResult
End Function

pFilter は、次のシグネチャを使用して IFilter を実装します。

Public Interface IFilter(Of T)
    Function Test(ByVal pObject As T) As Boolean
End Interface

私はポイントを破りpFilter.Test(o)ましたが、実際には呼び出されないことがわかりました。奇妙なことにpFilter.Test(o)、True に置き換えると、レコードのテーブル全体が期待どおりに表示されます。また、どのような場合でも、コンパイル時または実行時のエラーは発生しません。

私はLambdasLINQにかなり慣れていないので、達成しようとしていることの限界を理解していない可能性があることを十分に認識しています。どんな助けでも大歓迎です!

解決策: 著者が私を正しい道に導いてくれたので、私はすでに解決策をマークしました。この問題の本質は、.NET 関数を LINQ が SQL ステートメントに変換できるものに強制しようとしたことにあります (これは不可能です)。これを解決するために、Test メソッドに対して System.Linq.Expressions.Expression(Of Func(Of T, Boolean)) を返すように IFilter を変更しました。これで、述語を返す厳密に型指定されたフィルターを作成し、ラムダ式を使用せずに直接 Where() に渡すことができます。私はまた、LinqKitを使用して、同様のタスクを達成している可能性のある人がこの作業をより簡単に行えるようにしています。

4

1 に答える 1

1

あなたの問題が何であるかを見つけたと思います-IQueryableの概念を理解しています。この記事の内容は次のとおりです。 LazyList を使用した遅延読み込み

IQueryable は Linq To Sql の基礎であり、(私が思うに) キラー機能である遅延実行を備えています。IQueryable は基本的に、列挙可能なリストとして扱うことができる Expression を作成します。値を反復または要求する場合にのみ、クエリが実行されます。

したがって、おそらく結果を使用したことがなく、それが呼び出されなかった理由です。.NET フレームワークは、式ツリーを作成しただけで、処理は何もしませんでした。

参照: IQueryable と IEnumerable

于 2012-10-25T18:03:05.173 に答える