Expression.Or, параметр 'item' не входит в область действия

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

The parameter 'item' is not in scope.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The parameter 'item' is not in scope.

метод:

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

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

Выражения, являющиеся или были получены из метода ниже, который выполняется нормально. Если есть лучший способ или результаты, я все уши. Кроме того, я заранее не знаю, сколько их будет.

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

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

В качестве альтернативы, есть ли лучший способ сделать или? В настоящее время .Where (ограничение) отлично работает там, где ограничение имеет тип Expression>. Как я могу сделать where (constraint1 или constraint2) (к ограничению n'th)

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
4 271
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

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

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

Спасибо! Собираюсь попробовать передать тот же параметр сейчас

ccook 05.01.2009 01:25

Ты мой друг, потрясающий :)

ccook 05.01.2009 01:30

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

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

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

param1 != param2

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

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

Обновлено: Кроме того, если вы пытаетесь динамически составлять предложения where в LINQ, вы можете попробовать PredicateBuilder.

Спасибо :) Я переработал метод, чтобы передать тот же параметр в методы помощника, и все снова в порядке. Я смотрю в PredicateBuilder, чтобы, надеюсь, навести порядок.

ccook 05.01.2009 01:37

Будьте осторожны, поскольку PredicateBuilder от Ben & Joe Albahari не работает для Entity Framework. Смотрите мой ответ о фиксированной версии.

Alex Che 25.09.2012 20:40

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

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.

Будьте осторожны, поскольку этот код не работает для Entity Framework. Смотрите мой ответ о фиксированной версии.

Alex Che 25.09.2012 20:39

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

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

Тем, кто нашел эту страницу поисковой системой и собирается использовать PredicateBuilder от Бена и Джо Альбахари, будьте осторожны, так как это не работает с Entity Framework.

Вместо этого попробуйте эта фиксированная версия.

Другие вопросы по теме