Pregunta

Estoy intentando escribir una función estática en O dos expresiones, pero recibo el siguiente error:

  

El parámetro 'elemento' no está dentro del alcance.

     

Descripción: Una excepción no controlada   ocurrido durante la ejecución del   solicitud web actual. Por favor revise el   seguimiento de la pila para obtener más información acerca de   El error y donde se originó.   el código.

     

Detalles de la excepción:   System.InvalidOperationException: La   el parámetro 'item' no está dentro del alcance.

el 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 : agregar más información

Las expresiones que están siendo o están viniendo del método a continuación, que se ejecutan bien. Si hay una mejor manera de hacerlo o los resultados soy todo oídos. Además, no sé cuántos se están haciendo por adelantado.

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 : agregar aún más información

Alternativamente, ¿hay una mejor manera de hacer un o? Actualmente, la .Where (restricción) funciona bien donde la restricción es de tipo Expresión > ¿Cómo puedo hacer dónde? (Restricción1 o restricción2) (a la restricción n'th)

Gracias de antemano!

¿Fue útil?

Solución

El problema es que la expresión que está creando en el método OrExpressions reutiliza el cuerpo de las dos expresiones. Esos cuerpos contendrán referencias a su propia ParameterExpression que se ha definido en FilterExpression.

Una solución sería volver a escribir las partes izquierda y derecha para usar la nueva ParameterExpression. O pasar la ParameterExpression original a lo largo. No es porque los dos ParameterExpression tienen el mismo nombre que representan el mismo parámetro.

Otros consejos

Como ya se sugirió, aquí puede encontrar este código muy bueno (funcional)

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 puede adaptarse a sus necesidades y que no está vinculado (IMHO) a LINQ.

No estoy seguro de los términos adecuados aquí, pero básicamente los parámetros de expresión no son equivalentes incluso si tienen el mismo nombre.

Eso significa que

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

param1 != param2

param1 y param2 no serán lo mismo si se usan en una expresión.

La mejor manera de lidiar con esto es crear un parámetro por adelantado para tu expresión, y luego pasarlo a todas las funciones de ayuda que necesitan el parámetro.

EDITAR: Además, si está intentando componer dinámicamente las cláusulas where en LINQ, puede dar PredicateBuilder a try.

Para aquellos que encontraron esta página en un motor de búsqueda y usarán PredicateBuilder de Ben & Joe Albahari , tenga cuidado, ya que no funciona con Entity Framework .

Prueba esta versión corregida en su lugar.

La solución de Fabrizio también se me ocurrió también, pero como estaba intentando combinar dos expresiones que se ejecutarían como una consulta de sql 2 sql, pensé que se ejecutaría en la memoria en lugar del servidor sql.

Me escribieron: Linq-To-Sql reconoce que la invocación es de una expresión lambda y, por lo tanto, sigue produciendo sql optimizado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top