Pergunta

Estou tentando escrever uma função estática para duas expressões, mas recebo o seguinte erro:

O parâmetro 'item' não está no escopo.

Descrição:Uma exceção não tratada ocorreram durante a execução do solicitação web atual.Por favor, reveja o Rastreamento de pilha para obter mais informações sobre o erro e onde ele se originou em o código.

Detalhes da exceção:System.InvalidOperationException:O O parâmetro 'item' não está no escopo.

o método:

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

editar:adicionando mais informações

As expressões or'd vêm do método abaixo, que funciona perfeitamente.se existe uma maneira melhor ou os resultados sou todo ouvidos.Além disso, não sei quantos estão sendo agendados com antecedência.

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

editar:adicionando ainda mais informações

Alternativamente, existe uma maneira melhor de fazer um ou?Atualmente o .Where(constraint) funciona bem onde a restrição é do tipo Expression>.Como posso fazer where(restrição1 ou restrição2) (para a restrição n'ésima)

Desde já, obrigado!

Foi útil?

Solução

A questão é que a expressão que você está criando no método orexpressions reutiliza o corpo das duas expressões. Esses corpos conterão referências à sua própria parameterexpressão que foi definida na expressão do filtro.

Uma correção seria reescrever as partes esquerda e direita para usar a nova Parameterexpression. Ou passar a temerexpressão original. Não é porque as duas parameterexpressão têm o mesmo nome que representam o mesmo parâmetro.

Outras dicas

Como já sugerido, aqui Você pode encontrar este código muito bom (funcionando)

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

que você pode se adaptar às suas necessidades e que não está vinculado (IMHO) ao LINQ.

Não tenho certeza sobre os termos adequados aqui, mas basicamente os parâmetros de expressão não são equivalentes, mesmo que tenham o mesmo nome.

Isso significa que

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

param1 != param2

param1 e param2 não serão a mesma coisa se usados ​​em uma expressão.

A melhor maneira de lidar com isso é criar um parâmetro antecipadamente para sua expressão e, em seguida, passá-lo para todas as funções auxiliares que precisam do parâmetro.

EDITAR:Além disso, se você estiver tentando compor cláusulas where dinamicamente no LINQ, poderá fornecer PredicadoBuilder uma tentativa.

Para aqueles que encontraram esta página por um mecanismo de pesquisa e vão usar O PredicateBuilder de Ben e Joe Albahari, cuidado, já que não funciona com a estrutura da entidade.

Tentar esta versão fixa em vez de.

A solução de Fabrizio também me ocorreu também, mas como eu estava tentando combinar duas expressões que seriam executadas como uma consulta SQL LINQ 2, pensei que ela seria executada na memória e não no servidor SQL.

Fui escrito-Linq-to-SQL reconhece que a invocação é de expressão de Lambda e, portanto, ainda produz SQL otimizado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top