8

Or two 式に静的関数を書き込もうとしていますが、次のエラーが表示されます。

パラメータ 'item' はスコープ外です。

説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。

例外の詳細: System.InvalidOperationException: パラメーター 'item' はスコープ内にありません。

メソッド:

public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
    // Define the parameter to use
    var param = Expression.Parameter(typeof(T), "item");

    var filterExpression = Expression.Lambda<Func<T, bool>>
         (Expression.Or(
             left.Body,
             right.Body
          ), param);
    // Build the expression and return it
    return (filterExpression);
}

編集:さらに情報を追加

or'd されている式は、以下のメソッドから取得されており、正常に実行されます。より良い方法や結果があれば、私はすべて耳にします。また、事前にどれだけの数が実行中または実行中かわかりません。

public static Expression<Func<T, bool>> FilterExpression(string filterBy, object Value, FilterBinaryExpression binaryExpression)
{
    // Define the parameter to use
    var param = Expression.Parameter(typeof(T), "item");

    // Filter expression on the value
    switch (binaryExpression)
    {
        case FilterBinaryExpression.Equal:
            {
                // Build an expression for "Is the parameter equal to the value" by employing reflection
                var filterExpression = Expression.Lambda<Func<T, bool>>
                    (Expression.Equal(
                        Expression.Convert(Expression.Property(param, filterBy), typeof(TVal)),
                        Expression.Constant(Value)
                     ),
                    param);
                // Build the expression and return it
                return (filterExpression);
            }

編集:さらに情報を追加する

または、or を実行するより良い方法はありますか? 現在、.Where(constraint) は、制約が Expression> 型の場合に問題なく機能します。どこで(制​​約1または制約2)(制約n番目まで)を行うにはどうすればよいですか

前もって感謝します!

4

5 に答える 5

9

問題は、メソッド OrExpressions で作成している式が 2 つの式の本体を再利用することです。これらのボディには、FilterExpression で定義された独自の ParameterExpression への参照が含まれます。

修正は、新しい ParameterExpression を使用するように左右の部分を書き直すことです。または、元の ParameterExpression を渡します。2 つの ParameterExpression が同じ名前を持っているからといって、それらが同じパラメーターを表しているわけではありません。

于 2009-01-04T22:23:03.240 に答える
5

すでに提案したように、ここでこの非常に素晴らしい(動作する)コードを見つけることができます

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
    var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
    return Expression.Lambda<Func<T, bool>>(Expression.Or(expr1.Body, invokedExpr), expr1.Parameters);
}

ニーズに適応でき、LINQに関連付けられていない(IMHO)こと。

于 2009-01-05T13:46:12.287 に答える
3

ここでの適切な用語についてはわかりませんが、基本的に式のパラメーターは同じ名前であっても同等ではありません。

つまり、

var param1 = Expression.Parameter(typeof(T), "item");
var param2 = Expression.Parameter(typeof(T), "item");

param1 != param2

式で使用する場合、param1 と param2 は同じではありません。

これに対処する最善の方法は、式の前にパラメーターを 1 つ作成し、そのパラメーターを必要とするすべてのヘルパー関数に渡すことです。

編集: また、LINQ で where 句を動的に構成しようとしている場合は、PredicateBuilderを試してみてください。

于 2009-01-04T22:27:45.760 に答える
2

検索エンジンでこのページを見つけ、Ben&Joe Albahari の PredicateBuilderを使用しようとしている人は、Entity Framework では機能しないので注意してください。

代わりに、この修正版を試してください。

于 2012-09-25T16:38:30.493 に答える
1

ファブリツィオの解決策も思い浮かびましたが、linq 2 sql クエリとして実行される 2 つの式を結合しようとしていたため、SQL サーバーではなくメモリ内で実行されると考えました。

私は書かれました-Linq-To-Sqlは、呼び出しがラムダ式であることを認識し、最適化されたSQLを生成します。

于 2010-03-11T21:49:21.790 に答える