.Net Core EF如何组合多个条件表达式来过滤数据?
How to combine multiple condition expressions in .Net Core EF to filter data?
我正在使用以下代码根据动态列名称过滤记录
string[] colNames = {"firstName", "lastName", "Col3", "col4"}
string[] colValues = {"jac", "sam", "col3value","col4value"}
ParameterExpression param = Expression.Parameter(typeof(Student), "t");
MemberExpression column = Expression.Property(param, colNames[0]);
ConstantExpression searchValue = Expression.Constant(colValues[0]);
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
Expression exp = Expression.Call(column, containsMethod, searchValue);
var deleg = Expression.Lambda<Func<Student, bool>>(exp, param).Compile();
var students = context.StudentModel.Where(deleg).AsQueryable();
我如何为多列执行此操作(在我的例子中组合数组中的所有列)
ParameterExpression param = Expression.Parameter(typeof(Student), "t");
Expression groupExp = null;
foreach (PageFilter filter in query.PageFilters)
{
Expression con;
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
con = Expression.Call(Expression.Property(param, filter.Name), containsMethod, Expression.Constant(filter.Value));
groupExp = groupExp == null ? con : Expression.AndAlso(groupExp, con);
}
var deleg = Expression.Lambda<Func<Student, bool>>(groupExp, param);
var students = context.StudentModel.Where(deleg).AsQueryable();
这对我有用。
在这种情况下,基本方法是创建许多 Expression.Call
并将这些调用与 Expression.AndAlso
结合起来,正如 Svyatoslav Danyliv 所建议的那样。
它们必须共享相同的参数。
所以解决方案如下:
ParameterExpression param = Expression.Parameter(typeof(Student), "s");
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
Expression combinedExpression = null; // this will be passed to context.StudentModel.Where
for (int i = 0; i < colNames.Length; i++)
{
MemberExpression column = Expression.Property(param, colNames[i]);
ConstantExpression searchValue = Expression.Constant(colValues[i]);
Expression expression = Expression.Call(column, containsMethod, searchValue);
combinedExpression = combinedExpression == null
? expression;
: Expression.AndAlso(combinedExpression, expression);
}
您不需要编译 combinedExpression
,因为 .Where
请求 Expression<Func<...>>
,而不是 Func
本身。
`var students = context.StudentModel.Where(combinedExpression);
为了让所有过滤器正常工作,我假设您需要为不同的类型创建单独的表达式,例如int
、int?
也检查它们是否相等(或 >、=> 等)。因为目前 Contains
使用非常有限。
P.S。确保 colNames
数组中的 属性 名称正确,否则你会在 Expression.Property
调用时出错。
我正在使用以下代码根据动态列名称过滤记录
string[] colNames = {"firstName", "lastName", "Col3", "col4"}
string[] colValues = {"jac", "sam", "col3value","col4value"}
ParameterExpression param = Expression.Parameter(typeof(Student), "t");
MemberExpression column = Expression.Property(param, colNames[0]);
ConstantExpression searchValue = Expression.Constant(colValues[0]);
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
Expression exp = Expression.Call(column, containsMethod, searchValue);
var deleg = Expression.Lambda<Func<Student, bool>>(exp, param).Compile();
var students = context.StudentModel.Where(deleg).AsQueryable();
我如何为多列执行此操作(在我的例子中组合数组中的所有列)
ParameterExpression param = Expression.Parameter(typeof(Student), "t");
Expression groupExp = null;
foreach (PageFilter filter in query.PageFilters)
{
Expression con;
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
con = Expression.Call(Expression.Property(param, filter.Name), containsMethod, Expression.Constant(filter.Value));
groupExp = groupExp == null ? con : Expression.AndAlso(groupExp, con);
}
var deleg = Expression.Lambda<Func<Student, bool>>(groupExp, param);
var students = context.StudentModel.Where(deleg).AsQueryable();
这对我有用。
在这种情况下,基本方法是创建许多 Expression.Call
并将这些调用与 Expression.AndAlso
结合起来,正如 Svyatoslav Danyliv 所建议的那样。
它们必须共享相同的参数。
所以解决方案如下:
ParameterExpression param = Expression.Parameter(typeof(Student), "s");
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
Expression combinedExpression = null; // this will be passed to context.StudentModel.Where
for (int i = 0; i < colNames.Length; i++)
{
MemberExpression column = Expression.Property(param, colNames[i]);
ConstantExpression searchValue = Expression.Constant(colValues[i]);
Expression expression = Expression.Call(column, containsMethod, searchValue);
combinedExpression = combinedExpression == null
? expression;
: Expression.AndAlso(combinedExpression, expression);
}
您不需要编译 combinedExpression
,因为 .Where
请求 Expression<Func<...>>
,而不是 Func
本身。
`var students = context.StudentModel.Where(combinedExpression);
为了让所有过滤器正常工作,我假设您需要为不同的类型创建单独的表达式,例如int
、int?
也检查它们是否相等(或 >、=> 等)。因为目前 Contains
使用非常有限。
P.S。确保 colNames
数组中的 属性 名称正确,否则你会在 Expression.Property
调用时出错。