如何为LINQ to EF/SQL查询动态构建带OR谓词的查询语句
实现动态拼接OR谓词的LINQ to SQL查询方案
LINQ默认的链式Where调用只能生成AND拼接的条件,要实现OR拼接需要基于表达式树实现,最简便的方式是使用通用的PredicateBuilder工具类实现,无需引入第三方依赖,具体步骤如下:
- 首先将
PredicateBuilder工具类添加到你的项目中:
public static class PredicateBuilder { // 初始化AND拼接的基础谓词 public static Expression<Func<T, bool>> True<T>() => f => true; // 初始化OR拼接的基础谓词 public static Expression<Func<T, bool>> False<T>() => f => false; // 拼接OR条件 public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right) { var invokeExpr = Expression.Invoke(right, left.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.OrElse(left.Body, invokeExpr), left.Parameters); } // 拼接AND条件 public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right) { var invokeExpr = Expression.Invoke(right, left.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left.Body, invokeExpr), left.Parameters); } }
- 按照你的业务场景使用,示例代码如下:
// OR拼接初始值必须为False,保证第一个条件拼接逻辑正确 var condition = PredicateBuilder.False<User>(); if (age != null) { condition = condition.Or(x => x.Age == age); } if (name != null) { condition = condition.Or(x => x.Name == name); } // 最终传入拼接好的条件 var query = context.Users.Where(condition);
注意事项
- 该实现生成的表达式树可被LINQ to SQL正常解析为带OR的SQL语句,最终执行效果和你期望的
query.Where(x => x.Age == age || x.Name == name)完全一致。 - 如果后续需要同时混用AND和OR拼接,只需按逻辑调用对应的
And/Or扩展方法即可,AND拼接的初始值要设为True。
内容的提问来源于stack exchange,提问作者CSharpBeginner
相关产品推荐
相关产品推荐

