像以前没有使用EF时,对于从界面输入的多条件查询时,都是使用SQL语句的拼接,因为使用了哪几种条件是未知的。
类似下面这样
var sql = "select * from xxx where xxx";
if(!string.IsNullOrEmpty(xxid){ sql += “ And xxid = ” + xxid; }
这种方法虽然笨拙,但是能很好的解决问题。
使用EF后,也遇到同样的问题。在linq中是可以利用表达式树来实现组合条件查询的功能,但是需要一定的学习门槛。
如果你已经了解了基本的linq语法,但是又暂时没有时间学习表达式树,可以试试以下的简单方法。
原理很简单,执行多次where函数即可,这种方法虽然会增加循环次数,但是也算很好的解决了问题。
测试代码如下:
模型
public class Student{ public string Name { get; set; } public string StudentID { get; set; }}
功能实现
static void Main(string[] args){ List<Student> students = new List<Student>();
students.Add(new Student() { Name = "雍心慈", StudentID = "1" }); students.Add(new Student() { Name = "雍心慈2", StudentID = "2" }); students.Add(new Student() { Name = "乔宁夏", StudentID = "3" }); students.Add(new Student() { Name = "乔宁夏2", StudentID = "4" }); students.Add(new Student() { Name = "宓白夜", StudentID = "5" }); students.Add(new Student() { Name = "仰灵萱", StudentID = "6" }); students.Add(new Student() { Name = "冷杏儿", StudentID = "7" });
var query = students.AsEnumerable();
foreach (var rule in GetExpression("心","1")) { query = query.Where(x => rule(x)); }
foreach (var item in query) { Console.WriteLine(item.StudentID); Console.WriteLine(item.Name); }}
private static List<Func<Student, bool>> GetExpression(string name, string studentId){ List<Func<Student, bool>> list = new List<Func<Student, bool>>();
if (!string.IsNullOrEmpty(studentId)) { list.Add(x => x.StudentID.Contains(studentId)); }
if (!string.IsNullOrEmpty(name)) { list.Add(x => x.Name.Contains(name)); }
return list;}
如果想要减少循环次数,代码复杂一点,可以参考如下方法:
internal class Program{ static void Main(string[] args) { List<Student> students = new List<Student>();
students.Add(new Student() { Name = "雍心慈", StudentID = "1" }); students.Add(new Student() { Name = "雍心慈2", StudentID = "2" }); students.Add(new Student() { Name = "乔宁夏", StudentID = "3" }); students.Add(new Student() { Name = "乔宁夏2", StudentID = "4" }); students.Add(new Student() { Name = "宓白夜", StudentID = "5" }); students.Add(new Student() { Name = "仰灵萱", StudentID = "6" }); students.Add(new Student() { Name = "冷杏儿", StudentID = "7" }); var result = students.AsQueryable().Where(GetExpressionTree("心", "1"));
foreach (var item in result) { Console.WriteLine(item.StudentID); Console.WriteLine(item.Name); } }
private static Expression<Func<Student, bool>> GetExpressionTree(string name, string studentId) { Expression<Func<Student, bool>> expression = x => true;
var paramExpression = Expression.Parameter(typeof(Student));
if (!string.IsNullOrEmpty(name)) { Expression<Func<Student, bool>> nameExpression = x => x.Name.Contains(name); expression = ConcatExpression(expression, nameExpression, paramExpression); }
if (!string.IsNullOrEmpty(studentId)) { Expression<Func<Student, bool>> patientIdExpression = x => x.StudentID.Contains(studentId); expression = ConcatExpression(expression, patientIdExpression, paramExpression); }
return expression; }
private static Expression<Func<Student, bool>> ConcatExpression(Expression<Func<Student, bool>> left, Expression<Func<Student, bool>> right, ParameterExpression parameterExpression) { var expressionBody = Expression.AndAlso(left.Body, right.Body); expressionBody = (BinaryExpression)new ParameterReplacer(parameterExpression).Visit(expressionBody); return Expression.Lambda<Func<Student, bool>>(expressionBody, parameterExpression); } }
internal class ParameterReplacer : ExpressionVisitor { private readonly ParameterExpression _parameter;
protected override Expression VisitParameter(ParameterExpression node) { return base.VisitParameter(_parameter); }
internal ParameterReplacer(ParameterExpression parameter) { _parameter = parameter; } }
运行结果:
示例代码
https://github.com/zhaotianff/cnblog-demo-code/tree/main/ConcatExpression
参考:
https://stackoverflow.com/questions/6736505/how-to-combine-two-lambdas/6736589#6736589
https://stackoverflow.com/questions/457316/combining-two-expressions-expressionfunct-bool
https://stackoverflow.com/questions/1922497/how-do-i-combine-linq-expressions-into-one
https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/
该文章在 2026/1/20 10:26:55 编辑过