Estoy en el proceso de crear un sistema de filtrado más elaborado para este gran proyecto nuestro. Uno de los predicados principales es poder pasar comparaciones a través de un parámetro de cadena. Esto expresa en la forma siguiente: "> 50" o "5-10" o "< 123.2"Método de extensión que devuelve la expresión lambda a través de comparar
Lo que tengo (como un ejemplo para ilustrar)
ViewModel:
TotalCost (string) (value: "<50")
Required (string) (value: "5-10")
EF modelo:
TotalCost (double)
Required(double)
expresión que me gustaría utilizar:
model => model.Where(field => field.TotalCost.Compare(viewModel.TotalCost) && field.Required.Compare(viewModel.Required));
expresión que me gustaría recibir:
model => model.Where(field => field.TotalCost < 50 && field.Required > 5 && field.Required < 10);
O algo similar a la
Sin embargo ... no tengo idea de por dónde empezar. Yo he reducido a
public static Expression Compare<T>(this Expression<Func<T, bool>> value, string compare)
Puede que no sea incluso corregir, pero esto es sobre todo lo que tengo. El generador de la comparación no es el problema, eso es lo fácil. La parte difícil es en realidad devolver la expresión. Nunca intenté devolver expresiones como valores de función. Básicamente, lo que necesito conservar es el campo y devolver una expresión de comparación, más o menos.
¿Algún ayuda? : X
Actualización:
Por desgracia esto no resuelve mi problema. Puede ser porque he estado despierto durante las últimas 23 horas, pero no tengo la menor idea de cómo convertirlo en un método de extensión. Como ya he dicho, lo que me gustaría ... es básicamente una manera de escribir:
var ex = new ExTest();
var items = ex.Repo.Items.Where(x => x.Cost.Compare("<50"));
La forma di forma a cabo esa función (probablemente completamente equivocado) es
public static Expression<Func<decimal, bool>> Compare(string arg)
{
if (arg.Contains("<"))
return d => d < int.Parse(arg);
return d => d > int.Parse(arg);
}
Le falta el " este -algo- valor "para compararlo en primer lugar, y aún no he podido descifrar cómo hacer que sea capaz de obtener una entrada de expresión ... en cuanto a ReSharper, me sugiere que lo convierta en booleano ...
Mi cabeza está llena de pelusa en este momento ...
Actualización 2:
que logró encontrar una manera de tener un pedazo de código que funciona en un repositorio de memoria en una aplicación de consola. Todavía estoy por intentarlo con Entity Framework.
public static bool Compare(this double val, string arg)
{
var arg2 = arg.Replace("<", "").Replace(">", "");
if (arg.Contains("<"))
return val < double.Parse(arg2);
return val > double.Parse(arg2);
}
Sin embargo, dudo mucho que eso es lo que busco
Actualización 3:
derecho, después de sentarse y mirar a través de las expresiones lambda de nuevo, antes de la última respuesta, me vino con algo similar a lo siguiente, no cumple con los requisitos exactos de "Comparar()" pero es un método 'sobrecarga-ish' Donde:
public static IQueryable<T> WhereExpression<T>(this IQueryable<T> queryable, Expression<Func<T, double>> predicate, string arg)
{
var lambda =
Expression.Lambda<Func<T, bool>>(Expression.LessThan(predicate.Body, Expression.Constant(double.Parse(50.ToString()))));
return queryable.Where(lambda);
}
Sin embargo, a pesar de mis ojos, todo lo que parece lógico, consigo excepción de ejecución de:
System.ArgumentException was unhandled
Message=Incorrect number of parameters supplied for lambda declaration
Source=System.Core
StackTrace:
at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, Boolean tailCall, IEnumerable`1 parameters)
at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, ParameterExpression[] parameters)
Esta es la línea culpable obvio:
var lambda =
Expression.Lambda<Func<T, bool>>(Expression.LessThan(predicate.Body, Expression.Constant(double.Parse(50.ToString()))));
estoy muy cerca de la solución. Si puedo evitar ese error, creo que EF debería ser capaz de traducir eso en SQL. De lo contrario ... bueno, la última respuesta probablemente desaparecerá.
pienso, que su parte update2 no se ejecutará en SQL Server (EF). ¿Lo has intentado? –
Sí, acabo de hacer. Como hubiera pensado, tbh. – NeroS