.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);

为了让所有过滤器正常工作,我假设您需要为不同的类型创建单独的表达式,例如intint? 也检查它们是否相等(或 >、=> 等)。因为目前 Contains 使用非常有限。

P.S。确保 colNames 数组中的 属性 名称正确,否则你会在 Expression.Property 调用时出错。