技術的には、これを修正する正しい方法は、ラムダから式ツリーを受け入れてi
参照を評価するフレームワークです。つまり、特定のフレームワークに対する LINQ フレームワークの制限です。現在実行しようとしているのはi
、データベースから既知の型 (プロバイダー) へのメンバー アクセスとして解釈することです。ラムダ変数キャプチャの仕組みにより、i
ローカル変数は実際には、プロバイダーが認識しない、変な名前の隠しクラスのフィールドになります。
つまり、フレームワークの問題です。
本当にやり遂げなければならない場合は、次のように式を手動で作成できます。
ParameterExpression x = Expression.Parameter(typeof(RptCriteriaHint), "x");
var query = repo.Find(
Expression.Lambda<Func<RptCriteriaHint,bool>>(
Expression.Equal(
Expression.MakeMemberAccess(
x,
typeof(RptCriteriaHint).GetProperty("CriteriaTypeID")),
Expression.Constant(i)),
x)).ToList();
...しかし、それは単なるマゾヒズムです。
このエントリに対するあなたのコメントは、私にさらに説明するように促します.
ラムダは、正しい署名を持つデリゲート、または正しい署名のデリゲートの 2 つのタイプのいずれかに変換できExpression<TDelegate>
ます。外部データベースへの LINQ (あらゆる種類のメモリ内クエリとは対照的に) は、2 番目の種類の変換を使用して機能します。
コンパイラは、大まかに言えば、次の方法でラムダ式を式ツリーに変換します。
- 構文ツリーはコンパイラによって解析されます。これはすべてのコードで発生します。
- 構文ツリーは、変数のキャプチャを考慮して書き直されています。変数のキャプチャは、通常のデリゲートまたはラムダと同様です。したがって、表示クラスが作成され、キャプチャされたローカルがそれらに移動されます (これは、C# 2.0 匿名デリゲートでの変数キャプチャと同じ動作です)。
- 新しい構文ツリーはクラスへの一連の呼び出しに変換される
Expression
ため、実行時に、解析されたテキストを忠実に表すオブジェクト ツリーが作成されます。
外部データ ソースへの LINQ は、この式ツリーを取得してそのセマンティック コンテンツを解釈し、ツリー内のシンボリック式を、そのコンテキストに固有のもの (DB 内の列など) を参照するものとして解釈するか、変換する即時値として解釈することになっています。通常、System.Reflection は、この変換をガイドするフレームワーク固有の属性を探すために使用されます。
ただし、サブソニックは、ドメイン固有の対応を見つけることができないシンボリック参照を適切に処理していないようです。シンボリック参照を評価するのではなく、単なるパントです。したがって、これはサブソニックの問題です。