基于Expression Lambda表达式树的通用复杂查询构建器——《摘要篇》

基于表达式树的通用查询构造器 常见的使用Linq Expression的做法这种代码众多,随便一搜就是, 但几乎都是单个条件的,单层级的,只能简单组装,组装成如:

Field_A =1 and Field_B =2 Or Field_C=3 
--或者 
Field_A =1 and (Field_B =2 Or Field_C=3)
 

是否可以灵活的查询条件组合 &独立的分离式的描述式条件,描述与执行分离的 &适应任何DTO的通用方案呢。

我们先来考查一个最简单的Sql where 子句: Id=1 当中有三种节点,分别为字段名:id,比较符:=,查询值:1 通过观察,我们用Name来标识字段名,Op来标识比较符,Value来标识查询值,那么数据结构可以设计为 :

{ "Name" : "id", "Op" : "=", "Value" : 1 }
 

再来考查具有两个条件的子句:

Id=1 and name="MyName" 
 

比上一条多了逻辑符:“and”

那么我们添加两个节点,用Predicates来描述查询条件,用Lg来标识逻辑串接,数据结构可以设计为

 [ 
     {
      "lg" : "",
      	"Predicates" : {"Name" : "id", "Op" : "=", "Value" : 1 }
     },
     {
        "lg":"and",
      	"Predicates": { "Name" : "Name", "Op" : "=", "Value" : "MyName"}
     } 
 ] 
 

以下两条子句都比较常用,也都属于简单的子句,再来看稍微复杂点儿的子句:

Id>1 and Id<10 and (Name="MyName" or Name="HisName")
 

比上一条多了一对分组括号: 添加节点filters来容纳逻辑组合,数据结构可以设计为:

 { 
     "lg": "", 
     	"filters":
	[ 
		{ 
			"lg": "", 
          		"Predicates":[ { "lg": "", "Name": "id", "Op": ">", "Value": 1 } ]
         	}, 
         	{ 
			"lg": "and", 
          		"Predicates":[ { "lg": "", "Name": "id", "Op": "<", "Value": 10 } ] 
         	},
            	{
                	"lg": "and",
                	"Predicates":
            		[
                        	{"lg": "","Name": "name",  "Op": "=", "Value": "MyName"},         
                        	{"lg": "or","Name": "name","Op": "=","Value": "HisName"}
        		]
    		}
	]
}
 
--更复杂一点的等等:
Id=1 
 and (
     (Name="MyName" or Name="HisName") or (Phone like"13899%" and Emil Like "%@xx.com")
 )
 

基于此,期望能够以简洁的方式:

Query.Where(QueryFilterBuilder.CreateFilterExpression<Entity>(conditionBlock));

实现如下复杂的查询组合的复杂查询构建器:

where 
    ( 
        (            
            (A.Field_A + A.Field_B) / A.Field_C=(2+3) % 2 or A.Field_A= A.Field_C
			or (A.Field_C > 2 and Len(A.Field_D) < 2)
        ) 
        and (A.Field_E Like"%xxooxx" or A.Field_F in (1,2,3))
    ) 
    and A.Field_G in (select B.Field_N From B where cast(B.Fieild_DatetimeString as Datetime) = A.FieldDatetime)
)

如上所示,几乎可以实现任意条件,任意逻辑的组合查询。

理想这么美好,那么现实如何去实现,我们设计一个用来描述条件的对象:ConditionBlock用来承载上述查询条件的数据结构,再设计一个条件分析构造器:QueryFilterBuilder,使用它来创建Expression表达式树以构造Lambda查询表达式,由于条件描述与表达式构造分离,条件描述的工作可以放在任何地方,比如浏览器,它可以只需要提供符合数据结构的Json数据即可。

先看看总体代码:

https://github.com/ls0001/QueryFilter(别忘记随手点亮一颗小星星哦/^.^)

欲了解更多,挖掘更多,敬待下期分解。

 

 

posted @ 2023-05-12 16:38  Tongze  阅读(35)  评论(0编辑  收藏  举报