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

本系列将会写成一个长连载,所写内容居于本人开发的构架中部分开源模块。预设文章简要大纲如下

一、从构思说起 

  1.  
  2.  
  3.  

二、描述器的实现

  1.  
  2.  
  3.  

 三、表达式的组装

  1.  
  2.  
  3.  

四、拓展应用场景

  1.  
  2.  
  3.  

基于表达式树的通用查询构造器 常见的使用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数据即可。

posted @ 2023-05-12 16:58  Tongze  阅读(539)  评论(1编辑  收藏  举报