This is credit to @SvyatoslavDanyliv . Thanks man. Complete code link of @SvyatoslavDanyliv which I changed and only changed code is posted in the answer How to select many from string in efcore?
I modified your code only tow functions and it is achieved my target. Now I can post as much as possible condition from frontend. Following are the code which I modified and rest of the function is the same.
I want to return Expression instead of Querable return, want to add it into repository and can be used into my injected Services as parameters that can work along with other parameters.
Now working fine and thanks once again @SvyatoslavDanyliv your code helped me a lot. I am using Recursive function instead due to lack of time will continue to improve it to improve its performance.
public static Expression<Func<T, bool>> Where<T>(DbContext context, IList<qCondition.whereClause> filters)
{
IQueryable<T> returnResult = null;
var parameter = Expression.Parameter(typeof(T), "e");
Expression expression = Expression.Constant(true);
foreach (var key in filters)
{
if (key.condition == "()")
{
var dynamicQuery = FilterQuery(context.Model, parameter, key.field, propExpression =>
Expression.Call(EnsureString(propExpression), nameof(string.Contains), Type.EmptyTypes,
Expression.Constant(key.value)));
expression = Expression.AndAlso(expression, dynamicQuery);
}
else if (key.condition == "*=")
{
var dynamicQuery = FilterQuery(context.Model, parameter, key.field, propExpression =>
Expression.Call(EnsureString(propExpression), nameof(string.StartsWith), Type.EmptyTypes,
Expression.Constant(key.value)));
expression = Expression.AndAlso(expression, dynamicQuery);
}
else if (key.condition == "=*")
{
var dynamicQuery = FilterQuery(context.Model, parameter, key.field, propExpression =>
Expression.Call(EnsureString(propExpression), nameof(string.EndsWith), Type.EmptyTypes,
Expression.Constant(key.value)));
expression = Expression.AndAlso(expression, dynamicQuery);
}
else
{
var dynamicQuery = FilterQuery(context.Model, parameter,key.field, propExpression =>
{
if (key.value == null)
{
var propType = propExpression.Type;
if (propType.IsValueType)
{
propExpression = Expression.Convert(propExpression, typeof(Nullable<>).MakeGenericType(propType));
}
}
if(key.condition=="=")
return Expression.Equal(propExpression, Expression.Constant(Convert.ChangeType(key.value, propExpression.Type), propExpression.Type));
else if(key.condition=="!=")
return Expression.NotEqual(propExpression, Expression.Constant(Convert.ChangeType(key.value, propExpression.Type), propExpression.Type));
else if(key.condition=="<")
return Expression.LessThan(propExpression, Expression.Constant(Convert.ChangeType(key.value, propExpression.Type), propExpression.Type));
else if(key.condition==">")
return Expression.GreaterThan(propExpression, Expression.Constant(Convert.ChangeType(key.value, propExpression.Type), propExpression.Type));
else if(key.condition=="<=")
return Expression.LessThanOrEqual(propExpression, Expression.Constant(Convert.ChangeType(key.value, propExpression.Type), propExpression.Type));
else
return Expression.GreaterThanOrEqual(propExpression, Expression.Constant(Convert.ChangeType(key.value, propExpression.Type), propExpression.Type));
});
expression = Expression.AndAlso(expression, dynamicQuery);
}
}
var finalResult = Expression.Lambda<Func<T, bool>>(expression, parameter);
return finalResult;
//return query.Where(finalResult);
}
And another function which I eddited
private static Expression FilterQuery(IModel model, ParameterExpression exp, string propPath, Func<Expression, Expression> filterFactory)
{
var propNames = propPath.Split('.');
var parameter = exp;
var filter = BuildFilter(exp, model, propNames, 0, filterFactory);
// var filterLambda = Expression.Lambda<Func<T, bool>>(filter, entityParameter);
// return query.Where(filterLambda);
return filter;
}
Now I can pass as many as parameters with multiple conditions. Working with following input parameters
new List<parameters>
{
new parameter{key:"Name",operator:"=", value : "abcd"},
new parameter{key:"Students.Classes.Class.classTitle",operator:"()-Contains", value : "V"},
new parameter{key:"Students.BasicInformation.FirstName",operator:"*=", value : "xyz"},
}