es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

“Mayor o igual dinámico utilizando expresiones en ASP.NET Core.”

Me encuentro con un pequeño problema en el que estoy atascado. Estoy construyendo consultas de manera dinámica que serán utilizadas por LINQ para consultar la base de datos. El cálculo debe realizarse en el lado de la base de datos (la evaluación del lado del cliente no es eficiente, por lo tanto, no me gustaría usarla).

Tengo dos expresiones que se utilizan para calcular una operación matemática especial (para este contexto, se ha simplificado). Se representan como:

“`C#
public static Expression<><circle, float=””>> REAL_HEIGHT_EXPR = circle => circle.Diameter * circle.Paper.Height;
public static Expression<><circle, float=””>> REAL_Y_EXPR = circle => circle.Y * circle.Paper.Height – REAL_HEIGHT_EXPR.Invoke(circle) * (float)0.5;


Estoy buscando registros en la base de datos que se encuentran en un rango min-max. Dado que habrá múltiples pares de min-max, también estoy utilizando LinqKit (https://github.com/scottksmith95/LINQKit) con `PredicateBuilder`. Este `PredicateBuilder` se construirá gradualmente y luego se utilizará en un `LINQ .Where(predicate)`. Digamos, por ejemplo, que tenemos dos pares de min-max con los valores `[0,1]` y `[4,5]`. La consulta SQL que se debe ejecutar sería:

(REAL_Y_EXPR >= 0 AND REAL_Y_EXPR <= 1) OR (REAL_Y_EXPR >= 4 AND REAL_Y_EXPR <= 5)


Donde REAL_Y_EXPR es el resultado de la expresión definida anteriormente, utilizando la clase Circle y sus parámetros. (El resultado del cálculo, que es un flotante, y se ejecuta en el lado de la base de datos) Aquí hay un fragmento de la función que construye el predicado: ```C# public static ExpressionStarter<circle> GetMinMaxPredicate(List<searchminmax> searchList, Expression<><circle, float="">> expr) { var allParametersSearch = PredicateBuilder.New<circle>(); if (searchList != null) { searchList.ForEach(value => { var searchPredicateAND = PredicateBuilder.New<circle>(); if (value.Min != null) { searchPredicateAND = searchPredicateAND.And(circle => expr.Invoke(circle) >= value.Min); } if (value.Max != null) { searchPredicateAND = searchPredicateAND.And(circle => expr.Invoke(circle) <= value.Max); } allParametersSearch = allParametersSearch.Or(searchPredicateAND); }); } return allParametersSearch; }

La razón principal por la que estoy haciendo todo eso es tener un código completamente reutilizable y evitar volver a escribir la expresión varias veces.

Sin embargo, este código no funciona, ya que estoy obligado a llamar a Invoke(), LINQ lanzará que necesito llamar a ToList() u otros métodos para hacer una evaluación en el lado del cliente. (También he probado usando REAL_HEIGHT_EXPR que no tiene un Invoke(), y es el mismo error, por lo que no viene de esa parte)

El principal problema que tengo es el <= y >=. Como cambia y me gustaría usar la misma expresión sin tener que reescribir todas ellas varias veces con el operando incluido.

He intentado usar Expression.GreaterThanOrEqual con la expresión ya escrita (¡lo cual sería genial!)

Expression searchAND = Expression.Empty();
searchAND = Expression.AndAlso(searchAND, Expression.GreaterThanOrEqual(Expression.Constant(value.Min), REAL_Y_EXPR);

Sin embargo, la línea searchAND arroja el siguiente error:

Exception has occurred: CLR/System.InvalidOperationException
Exception thrown: 'System.InvalidOperationException' in System.Linq.Expressions.dll: 'The binary operator GreaterThanOrEqual is not defined for the types 'System.Single' and 'System.Func`2[My.NameSpace.Circle,System.Single]'.
   at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow(ExpressionType binaryType, String name, Expression left, Expression right, Boolean liftToNull)
   at System.Linq.Expressions.Expression.GetComparisonOperator(ExpressionType binaryType, String opName, Expression left, Expression right, Boolean liftToNull)
   at System.Linq.Expressions.Expression.GreaterThanOrEqual(Expression left, Expression right, Boolean liftToNull, MethodInfo method)
   at System.Linq.Expressions.Expression.GreaterThanOrEqual(Expression left, Expression right)

¿Alguien tendría alguna idea sobre cómo resolver eso?</circle,></circle,></circle,>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que estás intentando pasar una expresión como parámetro a una expresión de operador relacional, lo cual no es posible. Para resolver este problema, puedes usar Expression.Lambda() para convertir la expresión en un delegado antes de pasarla a la expresión de operador relacional. Aquí hay una versión actualizada del código:

    “`C#
    public static ExpressionStarter GetMinMaxPredicate(List searchList, Expression<><circle, float=””>> expr)
    {
    var allParametersSearch = PredicateBuilder.New();
    if (searchList != null)
    {
    searchList.ForEach(value =>
    {
    var searchPredicateAND = PredicateBuilder.New
    ();
    if (value.Min != null)
    {
    searchPredicateAND = searchPredicateAND.And(Expression.Lambda<><circle, bool=””>>(Expression.GreaterThanOrEqual(expr.Body, Expression.Constant(value.Min)), expr.Parameters));
    }

            if (value.Max != null)
            {
                searchPredicateAND = searchPredicateAND.And(Expression.Lambda<><circle, bool="">>(Expression.LessThanOrEqual(expr.Body, Expression.Constant(value.Max)), expr.Parameters));
            }
    
            allParametersSearch = allParametersSearch.Or(searchPredicateAND);
        });
    }
    
    return allParametersSearch;
    

    }
    “`

    En esta versión actualizada, estamos usando Expression.Lambda() para convertir el expr.Body en una expresión lambda utilizando la misma lista de parámetros que expr. Luego podemos usar esta expresión lambda con la expresión de operador relacional.

    Ten en cuenta que estamos usando LessThanOrEqual() en lugar de GreaterThanOrEqual() para el parámetro Max porque queremos verificar si la expresión es menor o igual al valor Max, no mayor o igual a él.</circle,></circle,></circle,>

Comments are closed.