所有
我尝试通过表达式树构建动态linq查询,下面是我的代码
Expression<Func<User, bool>> filter = c => c.isAdmin == false;
Expression<Func<User, bool>> filterForExistUser = c => (c.isfreezed == null ? false : c.isfreezed) != true;
Expression<Func<User, bool>> finalFilter = Expression.Lambda<Func<User, bool>>(Expression.AndAlso(filter.Body, filterForExistUser.Body), filter.Parameters);
IQueryable<User> myusers = db.Users.AsQueryable<User>();
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { myusers.ElementType },
myusers.Expression,
finalFilter);
IQueryable<User> results = myusers.Provider.CreateQuery<User>(whereCallExpression);
foreach (User user in results)
Console.WriteLine(user.UserName);
但系统报告&#34; unding参数c&#34;错误,我该如何解决?
由于
答案 0 :(得分:0)
虽然filter
和filterForExistUser
表达式中的参数共享相同的名称,但它们都指的是来自不同范围的不同符号。您的新表达式使用filter
表达式中的参数,但您遗漏了filterForExistUser
的参数。您必须重写表达式,以便在整个表达式中使用相同的单个参数。
这是一个可用于组合谓词的通用方法:
Expression<Func<TSource, bool>> CombinePredicates<TSource>(
Expression<Func<TSource, bool>> head,
params Expression<Func<TSource, bool>>[] tail)
{
var param = head.Parameters.Single();
var body = tail.Aggregate(
head.Body,
(result, expr) => Expression.AndAlso(result,
new SubstitutionVisitor
{
OldExpr = expr.Parameters.Single(),
NewExpr = param,
}.Visit(expr.Body)
)
);
return Expression.Lambda<Func<TSource, bool>>(body, param);
}
public class SubstitutionVisitor : ExpressionVisitor
{
public Expression OldExpr { get; set; }
public Expression NewExpr { get; set; }
public override Expression Visit(Expression node)
{
return (node == OldExpr) ? NewExpr : base.Visit(node);
}
}
密钥是SubstitutionVisitor
,用于使用“head”参数替换“tail”参数。
所以你的最终过滤器会变成这样:
Expression<Func<User, bool>> finalFilter =
CombinePredicates(filter, filterForExistUser);