Expression.Or, параметр 'item' находится вне области видимости - PullRequest
8 голосов
/ 05 января 2009

Я пытаюсь написать статическую функцию или два выражения, но получаю следующую ошибку:

Параметр 'item' находится вне области действия.

Описание: необработанное исключение произошло во время исполнения текущий веб-запрос. Пожалуйста, просмотрите трассировка стека для получения дополнительной информации о ошибка и откуда она возникла код.

Сведения об исключении: 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);
}

edit : добавление дополнительной информации

Выражения 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);
            }

edit : добавление дополнительной информации

В качестве альтернативы, есть лучший способ сделать или? В настоящее время .Where (ограничение) работает отлично, если ограничение имеет тип Expression>. Как я могу сделать, где (ограничение 1 или ограничение 2) (с ограничением N)

Заранее спасибо!

Ответы [ 5 ]

9 голосов
/ 05 января 2009

Проблема в том, что выражение, которое вы создаете в методе OrExpressions, повторно использует тело двух выражений. Эти тела будут содержать ссылки на их собственное выражение ParameterExpression, которое было определено в FilterExpression.

Исправление будет состоять в том, чтобы переписать левую и правую части, чтобы использовать новое выражение ParameterExpression. Или передать оригинальное выражение ParameterExpression. Это не потому, что два ParameterExpression имеют одно и то же имя, что они представляют один и тот же параметр.

5 голосов
/ 05 января 2009

Как уже предлагалось, здесь вы можете найти этот очень хороший (рабочий) код

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);
}

, который вы можете адаптировать к вашим потребностям и который не привязан (IMHO) к LINQ.

2 голосов
/ 25 сентября 2012

Для тех, кто нашел эту страницу поисковой системой и собирается использовать PredicateBuilder от Ben & Joe Albahari , обратите внимание, поскольку он не работает с Entity Framework .

Попробуйте эту фиксированную версию .

2 голосов
/ 05 января 2009

Я не уверен насчет правильных терминов здесь, но в основном параметры выражения не эквивалентны, даже если они имеют одинаковые имена.

Это означает, что

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

param1 != param2

param1 и param2 не будут одинаковыми при использовании в выражении.

Лучший способ справиться с этим - сначала создать один параметр для вашего выражения, а затем передать его всем вспомогательным функциям, которым требуется этот параметр.

РЕДАКТИРОВАТЬ: Кроме того, если вы пытаетесь динамически составить, где предложения в LINQ, вы можете попробовать PredicateBuilder .

1 голос
/ 12 марта 2010

Решение Fabrizio также пришло мне в голову, но, поскольку я пытался объединить два выражения, которые будут выполняться как запрос sql linq 2, я думал, что он будет выполняться в памяти, а не на сервере sql.

Мне было написано - Linq-To-Sql распознает, что вызов имеет лямбда-выражение и, таким образом, все еще производит оптимизированный sql.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...