目录创建QueryEntity类创建OperatorEnum类创建ExpressionExtension类使用示例单条件查询多条件查询多表查询上一篇文章提到了一些概念性的东西关于表达式,其实也是为本文做的知识准备。为了实现EFCore的多条件、连表查询,简化查询代码编写,特出此文。在一些管理后台,多条件查询数据是很常见的。比如在用户列表中,需要实现“用户名”、“手机号”、“账号是否被冻结”等一系列条件查询,常见的处理方式是拼接通过一系列的if...else...来判断条件,这就导致了一堆看起来有用但实际上实现查询接口很麻烦的代码。因此,根据前后端请求报文的协商,我们可以按照一定的格式动态创建一棵表达式树。创建QueryEntity类QueryEntity是前端传递给API的参数列表。通过这个类,服务端可以知道前端需要查询哪些字段,用什么方法(Equals,Contains)来过滤。//////查询实体///publicclassQueryEntity{//////字段名///publicstringKey{get;放;}/////值///publicstringValue{get;放;}//////操作方法,对应OperatorEnum枚举类///publicstringOperator{get;放;}//////逻辑运算符,只有AND,OR///publicstringLogicalOperator{get;放;}}CreateOperatorEnumclassOperatorEnum这是一个操作方法的枚举类,指定了API允许的查询方式,如Equals、Contains等。//////操作方法枚举///publicenumOperatorEnum{//////等于///等于,//////不等于///NotEqual,//////包含///包含,//////以什么开头///StartsWith,//////以什么结尾///EndsWith,//////大于///大于,/////大于或等于///GreaterEqual,//////小于///Less,//////小于orequalto///LessEqual,}创建ExpressionExtension类ExpressionExtension类实现表达式树的动态创建,将从前端传入的多条件查询转化为表达式,供EFCore查询.//////表达式扩展//////泛型publicstaticclassExpressionExtensionwhereT:class,new(){//////表达式动态拼接///publicstaticExpression>ExpressionSplice(Listentities){if(entities.Count<1){返回ex=>真;}varexpression_first=CreateExpressionDelegate(entities[0]);foreach(varentityinentities.Skip(1)){varexpression=CreateExpressionDelegate(entity);InvocationExpression调用=Expression.Invoke(expression_first,expression.Parameters.Cast());BinaryExpression二进制;//递归运算符号判定if(entity.LogicalOperator.ToUpper().Equals("OR")){binary=Expression.Or(expression.Body,调用);}else{binary=Expression.And(expression.Body,invocation);}expression_first=Expression.Lambda>(binary,expression.Parameters);}返回expression_first;}//////创建Expression///privatestaticExpression>CreateExpressionDelegate(QueryEntityentity){ParameterExpressionparam=Expression.Parameter(typeof(T));表达式键=参数;varentityKey=entity.Key.Trim();//包含'.',说明是父表的字符串if(entityKey.Contains('.')){vartableNameAndField=entityKey.Split('.');key=Expression.Property(key,tableNameAndField[0].ToString());key=Expression.Property(key,tableNameAndField[1].ToString());}别的{key=Expression.Property(key,entityKey);}表达式值=Expression.Constant(ParseType(entity));表达式主体=CreateExpression(key,value,entity.Operator);varlambda=Expression.Lambda>(body,param);返回拉姆达;}//////属性类型转换//////查询实体//私有静态对象ParseType(QueryEntityentity){try{PropertyInfo属性;//包含'.',说明是子类字段if(entity.Key.Contains('.')){vartableNameAndField=entity.Key.Split('.');property=typeof(T).GetProperty(tableNameAndField[0],BindingFlags.IgnoreCase|BindingFlags.Public|BindingFlags.Instance);属性=property.PropertyType.GetProperty(tableNameAndField[1],BindingFlags.IgnoreCase|BindingFlags.Public|BindingFlags.Instance);}else{property=typeof(T).GetProperty(entity.Key,BindingFlags.IgnoreCase|BindingFlags.Public|BindingFlags.Instance);}返回Convert.ChangeType(entity.Value,property.PropertyType);}catch(Exception){thrownewArgumentException("字段类型转换失败:字段名错误或值类型不正确");}}//////创建表达式///privatestaticExpressionCreateExpression(Expressionleft,Expressionvalue,stringentityOperator){if(!Enum.TryParse(entityOperator,true,outOperatorEnumoperatorEnum)){thrownewArgumentException("操作方法不存在,请检查operator的值");}返回operatorEnum开关{OperatorEnum.Equals=>Expression.Equal(left,Expression.Convert(value,left.Type)),OperatorEnum.NotEqual=>Expression.NotEqual(left,Expression.Convert(value,left.Type)),OperatorEnum.Contains=>Expression.Call(左,typeof(string).GetMethod("Contains",newType[]{typeof(string)}),value),OperatorEnum.StartsWith=>Expression.Call(left,typeof(string).GetMethod("StartsWith",newType[]{typeof(string)}),value),OperatorEnum.EndsWith=>Expression.Call(left,typeof(string).GetMethod("EndsWith",newType[]{typeof(string)}),value),OperatorEnum.Greater=>Expression.GreaterThan(left,Expression.Convert(value,left.Type)),OperatorEnum.GreaterEqual=>Expression.GreaterThanOrEqual(left,Expression.Convert(value,left.Type))),OperatorEnum.Less=>Expression.LessThan(left,Expression.Convert(value,left.Type)),OperatorEnum.LessEqual=>Expression.LessThanOrEqual(left,Expression.Convert(value,left.Type)),_=>Expression.Equal(left,Expression.Convert(value,left.Type)),};}}使用示例例如有下面两个实体类,Address是User的子类publicclassUser{publicintId{get;放;}公共字符串名称{得到;放;}=string.Empty;publicintAge}publicDateTimeCreateTime{get;放;}publicAddress地址{get;放;}}publicclassAddress{publicstringProvince{get;放;}publicstringCity{get;放;}}单条件Query查询用户表名(name)是否包含"chen":Listlist=newList{newQueryEntity{Key="name",Value="chen",Operator="Contains"}};varexpression=ExpressionExtension.ExpressionSplice(列表);//expression=Param_0=>Param_0.Name.Contains("chen")查询用户表中的年龄(age)大于或等于18:Listlist=newList{newQueryEntity{Key="age",Value="18",Operator="GreaterEqual"}};varexpression=ExpressionExtension.ExpressionSplice(列表);//expression=Param_0=>Param_0.Name.GreaterThanOrEqual(18)多条件查询查询用户表名(name)包含"chen"且年龄(age)大于等于18:Listlist=newList{newQueryEntity{Key="name",Value="chen",Operator="Contains"},newQueryEntity{Key="age",Value="18",Operator="GreaterEqual",//注意:这里必须填写“AND”,表示两个条件之间的关系。如果需要查询姓名中包含“chen”或者年龄大于等于18,则填写“OR”"logicalOperator":"AND"}};varexpression=ExpressionExtension.ExpressionSplice(列表);//表达式=Param_0=>((Param_0.Status>=Convert(1,Int32))和Invoke(Param_1=>Param_1.OpenId.Contains("9JJdFTVt6oimCgdbW61sk"),Param_0))多表查询查询用户表名(name)包含"chen"和广东省地址(address):Listlist=newList{newQueryEntity{Key="name",Value="chen",Operator="Contains"},newQueryEntity{Key="address.Province",Value="GuangdongProvince",Operator="Equals",//注意:这里必须填写“AND”,代表两个条件之间的关系。如果需要查询姓名中包含“chen”或者年龄大于等于18,则填写“OR”"logicalOperator":"AND"}};varexpression=ExpressionExtension.ExpressionSplice(列表);//expression={Param_0=>((Param_0.Address.Province==Convert("GuangdongProvince",String))AndInvoke(Param_1=>Param_1.Name.Contains("chen"),Param_0))}到目前为止,这篇关于C#表达式树Expression动态创建表达式的文章已经介绍过了。希望对大家的学习有所帮助,希望大家多多支持。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: