現在、一連のデータベース結果セットのラッパー オブジェクトを作成しています。そうしているうちに、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 に置き換えると、レコードのテーブル全体が期待どおりに表示されます。また、どのような場合でも、コンパイル時または実行時のエラーは発生しません。
私はLambdasとLINQにかなり慣れていないので、達成しようとしていることの限界を理解していない可能性があることを十分に認識しています。どんな助けでも大歓迎です!
解決策: 著者が私を正しい道に導いてくれたので、私はすでに解決策をマークしました。この問題の本質は、.NET 関数を LINQ が SQL ステートメントに変換できるものに強制しようとしたことにあります (これは不可能です)。これを解決するために、Test メソッドに対して System.Linq.Expressions.Expression(Of Func(Of T, Boolean)) を返すように IFilter を変更しました。これで、述語を返す厳密に型指定されたフィルターを作成し、ラムダ式を使用せずに直接 Where() に渡すことができます。私はまた、LinqKitを使用して、同様のタスクを達成している可能性のある人がこの作業をより簡単に行えるようにしています。