C#如何简单地组合linq查询条件

像以前没有使用EF时,对于从界面输入的多条件查询时,都是使用SQL语句的拼接,因为使用了哪几种条件是未知的。

类似下面这样

复制代码
var sql = "select * from xxx where xxx";

if(!string.IsNullOrEmpty(xxid)
     {
          sql += “  And xxid = ” + xxid; 
     }

这种方法虽然笨拙,但是能很好的解决问题。

使用EF后,也遇到同样的问题。在linq中是可以利用表达式树来实现组合条件查询的功能,但是需要一定的学习门槛。

如果你已经了解了基本的linq语法,但是又暂时没有时间学习表达式树,可以试试以下的简单方法。

原理很简单,执行多次where函数即可,这种方法虽然会增加循环次数,但是也算很好的解决了问题。

测试代码如下:

模型

复制代码
1     public  class Student
2     {
3         public string Name { get; set; }
4         public string StudentID { get; set; }
5     }

功能实现

复制代码
 1 static void Main(string[] args)
 2         {
 3             List<Student> students = new List<Student>();
 4 
 5             students.Add(new Student() { Name = "雍心慈", StudentID = "1" });
 6             students.Add(new Student() { Name = "雍心慈2", StudentID = "2" });
 7             students.Add(new Student() { Name = "乔宁夏", StudentID = "3" });
 8             students.Add(new Student() { Name = "乔宁夏2", StudentID = "4" });
 9             students.Add(new Student() { Name = "宓白夜", StudentID = "5" });
10             students.Add(new Student() { Name = "仰灵萱", StudentID = "6" });
11             students.Add(new Student() { Name = "冷杏儿", StudentID = "7" });
12 
13             var query = students.AsEnumerable();
14 
15             foreach (var rule in GetExpression("心","1"))
16             {
                   //循环执行过滤条件
17                 query = query.Where(x => rule(x));
18             }
19 
20             foreach (var item in query)
21             {
22                 Console.WriteLine(item.StudentID);
23                 Console.WriteLine(item.Name);
24             }
25         }
26 
27         private static List<Func<Student, bool>> GetExpression(string name, string studentId)
28         {
29             List<Func<Student, bool>> list = new List<Func<Student, bool>>();
30 
31             if (!string.IsNullOrEmpty(studentId))
32             {
33                 list.Add(x => x.StudentID.Contains(studentId));
34             }
35 
36             if (!string.IsNullOrEmpty(name))
37             {
38                 list.Add(x => x.Name.Contains(name));
39             }
40 
41             return list;
42         }

如果想要减少循环次数,代码复杂一点,可以参考如下方法:

复制代码
 1  internal class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //构建 一个测试列表
 6             List<Student> students = new List<Student>();
 7 
 8             students.Add(new Student() { Name = "雍心慈", StudentID = "1" });
 9             students.Add(new Student() { Name = "雍心慈2", StudentID = "2" });
10             students.Add(new Student() { Name = "乔宁夏", StudentID = "3" });
11             students.Add(new Student() { Name = "乔宁夏2", StudentID = "4" });
12             students.Add(new Student() { Name = "宓白夜", StudentID = "5" });
13             students.Add(new Student() { Name = "仰灵萱", StudentID = "6" });
14             students.Add(new Student() { Name = "冷杏儿", StudentID = "7" });
15 
               //通过名字和Id进行过滤
16             var result = students.AsQueryable().Where(GetExpressionTree("心", "1"));
17 
18             foreach (var item in result)
19             {
20                 Console.WriteLine(item.StudentID);
21                 Console.WriteLine(item.Name);
22             }
23         }40 
           //通过条件构建表达式树
41         private static Expression<Func<Student, bool>> GetExpressionTree(string name, string studentId)
42         {
43             Expression<Func<Student, bool>> expression = x => true;
44 
45             var paramExpression = Expression.Parameter(typeof(Student));
46 
47             if (!string.IsNullOrEmpty(name))
48             {
49                 //名字条件
50                 Expression<Func<Student, bool>> nameExpression = x => x.Name.Contains(name);
51                 expression = ConcatExpression(expression, nameExpression, paramExpression);
52             }
53 
54             if (!string.IsNullOrEmpty(studentId))
55             {
56                 //Id条件
57                 Expression<Func<Student, bool>> patientIdExpression = x => x.StudentID.Contains(studentId);
58                 expression = ConcatExpression(expression, patientIdExpression, paramExpression);
59             }  
60 
61             return expression;
62         }
63 
64         /// <summary>
65         /// 将表达式组合在一起
66         /// </summary>
67         /// <param name="left"></param>
68         /// <param name="right"></param>
69         /// <param name="parameterExpression"></param>
70         /// <returns></returns>
71         private static Expression<Func<Student, bool>> ConcatExpression(Expression<Func<Student, bool>> left, Expression<Func<Student, bool>> right, ParameterExpression parameterExpression)
72         {
73             var expressionBody = Expression.AndAlso(left.Body, right.Body);
74             expressionBody = (BinaryExpression)new ParameterReplacer(parameterExpression).Visit(expressionBody);
75             return Expression.Lambda<Func<Student, bool>>(expressionBody, parameterExpression);
76         }
77     }
78 
79     /// <summary>
80     /// 重写表达式树。
81     /// </summary>
82     internal class ParameterReplacer : ExpressionVisitor
83     {
84         private readonly ParameterExpression _parameter;
85 
86         protected override Expression VisitParameter(ParameterExpression node)
87         {
88             return base.VisitParameter(_parameter);
89         }
90 
91         internal ParameterReplacer(ParameterExpression parameter)
92         {
93             _parameter = parameter;
94         }
95     }

运行结果:

示例代码

参考:

c# - How to Combine two lambdas - Stack Overflow

c# - Combining two expressions (Expression<Func<T, bool>>) - Stack Overflow

How do I combine LINQ expressions into one? - Stack Overflow

Expression Trees - C# | Microsoft Learn

相关推荐
向宇it41 分钟前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
坐井观老天7 小时前
在C#中使用资源保存图像和文本和其他数据并在运行时加载
开发语言·c#
pchmi9 小时前
C# OpenCV机器视觉:模板匹配
opencv·c#·机器视觉
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭11 小时前
C#都可以找哪些工作?
开发语言·c#
boligongzhu12 小时前
Dalsa线阵CCD相机使用开发手册
c#
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇23】C#面向对象继承——`as`类型转化和`is`类型检查、向上转型和向下转型、里氏替换原则(LSP)
java·开发语言·unity·c#·游戏引擎·里氏替换原则
sukalot1 天前
windows C#-命名实参和可选实参(下)
windows·c#
小码编匠1 天前
.NET 下 RabbitMQ 队列、死信队列、延时队列及小应用
后端·c#·.net