相信在使用EF的时候对查询条件或者排序上的处理令人心烦,下面我们就来动态拼接表达式解决这一问题

当我们在查询中使用Where的时候可以看到如下参数

下面我们就来扩展 Expression<Func<T,bool>> 这个参数

第一步: 建立处理功能类

首先我们要创建一个查询条件转化为表达式的泛型功能类 如 UosoExpressionParser<T> 至于为什么要用泛型类目的很明确就是为了适配不同的模型参数

转化条件为表达式 那么处理一个方法来接受条件 返回表达式,条件可以按照自己的模式去设置

  1. public Expression<Func<T, bool>> ParserConditions(IEnumerable<UosoConditions> conditions)
  2. {
  3. //将条件转化成表达是的Body
  4. var query = ParseExpressionBody(conditions);
  5. return Expression.Lambda<Func<T, bool>>(query, parameter);
  6. }
  1. public class UosoConditions
  2. {
  3. /// <summary>
  4. /// 字段名称
  5. /// </summary>
  6. public string Key { get; set; }
  7. /// <summary>
  8. /// 值
  9. /// </summary>
  10. public string Value { get; set; }
  11. /// <summary>
  12. /// 值类型
  13. /// </summary>
  14. public string ValueType { get; set; }
  15. /// <summary>
  16. ///
  17. /// </summary>
  18. public UosoOperatorEnum Operator { get; set; }
  19. }

第二步: 条件转表达式具体处理

具体去实现  ParseExpressionBody 条件 枚举提供操作方式 如:(like 、 = 、!= 、>   、<  、>=  、<=  、in 、 between)

  1. private Expression ParseExpressionBody(IEnumerable<UosoConditions> conditions)
  2. {
  3. if (conditions == null || conditions.Count() == )
  4. {
  5. return Expression.Constant(true, typeof(bool));
  6. }
  7. else if (conditions.Count() == )
  8. {
  9. return ParseCondition(conditions.First());
  10. }
  11. else
  12. {
  13. Expression left = ParseCondition(conditions.First());
  14. Expression right = ParseExpressionBody(conditions.Skip());
  15. return Expression.AndAlso(left, right);
  16. }
  17. }
  1. private Expression ParseCondition(UosoConditions condition)
  2. {
  3. ParameterExpression p = parameter;
  4. Expression key = Expression.Property(p, condition.Key);
  5. Expression value = Expression.Constant(condition.Value);
  6. switch (condition.Operator)
  7. {
  8. case UosoOperatorEnum.Contains:
  9. return Expression.Call(key, typeof(string).GetMethod("Contains",new Type[] { typeof(string) }), value);
  10. case UosoOperatorEnum.Equal:
  11. return Expression.Equal(key, Expression.Convert(value, key.Type));
  12. case UosoOperatorEnum.Greater:
  13. return Expression.GreaterThan(key, Expression.Convert(value, key.Type));
  14. case UosoOperatorEnum.GreaterEqual:
  15. return Expression.GreaterThanOrEqual(key, Expression.Convert(value, key.Type));
  16. case UosoOperatorEnum.Less:
  17. return Expression.LessThan(key, Expression.Convert(value, key.Type));
  18. case UosoOperatorEnum.LessEqual:
  19. return Expression.LessThanOrEqual(key, Expression.Convert(value, key.Type));
  20. case UosoOperatorEnum.NotEqual:
  21. return Expression.NotEqual(key, Expression.Convert(value, key.Type));
  22. case UosoOperatorEnum.In:
  23. return ParaseIn(p, condition);
  24. case UosoOperatorEnum.Between:
  25. return ParaseBetween(p, condition);
  26. default:
  27. throw new NotImplementedException("不支持此操作");
  28. }
  29. }

这里对 In  和between 做了特殊处理

  1. private Expression ParaseBetween(ParameterExpression parameter, UosoConditions conditions)
  2. {
  3. ParameterExpression p = parameter;
  4. Expression key = Expression.Property(p, conditions.Key);
  5. var valueArr = conditions.Value.Split(',');
  6. if (valueArr.Length != )
  7. {
  8. throw new NotImplementedException("ParaseBetween参数错误");
  9. }
  10. try
  11. {
  12. int.Parse(valueArr[]);
  13. int.Parse(valueArr[]);
  14. }
  15. catch {
  16. throw new NotImplementedException("ParaseBetween参数只能为数字");
  17. }
  18. Expression expression = Expression.Constant(true, typeof(bool));
  19. //开始位置
  20. Expression startvalue = Expression.Constant(int.Parse(valueArr[]));
  21. Expression start = Expression.GreaterThanOrEqual(key, Expression.Convert(startvalue, key.Type));
  22.  
  23. Expression endvalue = Expression.Constant(int.Parse(valueArr[]));
  24. Expression end = Expression.GreaterThanOrEqual(key, Expression.Convert(endvalue, key.Type));
  25. return Expression.AndAlso(start, end);
  26. }
  1. private Expression ParaseIn(ParameterExpression parameter, UosoConditions conditions)
  2. {
  3. ParameterExpression p = parameter;
  4. Expression key = Expression.Property(p, conditions.Key);
  5. var valueArr = conditions.Value.Split(',');
  6. Expression expression = Expression.Constant(true, typeof(bool));
  7. foreach (var itemVal in valueArr)
  8. {
  9. Expression value = Expression.Constant(itemVal);
  10. Expression right = Expression.Equal(key, Expression.Convert(value, key.Type));

  11. expression = Expression.Or(expression, right);
  12. }
  13. return expression;
  14. }

第三步: 扩展分页、排序、查询条件

扩展 IQueryable<T> 就OK了,下面是我扩展的查询 排序 分页处理

扩展查询

  1. public static IQueryable<T> QueryConditions<T>(this IQueryable<T> query, IEnumerable<UosoConditions> conditions)
  2. {
  3. var parser = new UosoExpressionParser<T>();
  4. var filter = parser.ParserConditions(conditions);
  5. return query.Where(filter);
  6. }

扩展多条件排序

  1. public static IQueryable<T> OrderConditions<T>(this IQueryable<T> query, IEnumerable<UosoOrderConditions> orderConditions)
  2. {
  3. foreach (var orderinfo in orderConditions)
  4. {
  5. var t = typeof(T);
  6. var propertyInfo = t.GetProperty(orderinfo.Key);
  7. var parameter = Expression.Parameter(t);
  8. Expression propertySelector = Expression.Property(parameter, propertyInfo);
  9.  
  10. var orderby = Expression.Lambda<Func<T, object>>(propertySelector, parameter);
  11. if (orderinfo.Order == OrderSequence.DESC)
  12. query = query.OrderByDescending(orderby);
  13. else
  14. query = query.OrderBy(orderby);
  15.  
  16. }
  17. return query;
  18. }

扩展分页

  1. public static IQueryable<T> Pager<T>(this IQueryable<T> query, int pageindex, int pagesize,out int itemCount)
  2. {
  3. itemCount = query.Count();
  4. return query.Skip((pageindex - ) * pagesize).Take(pagesize);
  5. }

扩展基本完成了,接下来就是使用方式 下面是我写的查询分页方式

第四步: 具体使用方式

  1. public IList<IdentityUser> GetPagedList2(IEnumerable<UosoConditions> conditions,IEnumerable<UosoOrderConditions> orderConditions,int pageIndex, int pageSize,out int itemcount)
  2. {
  3. return _userManager.Users.AsNoTracking().QueryConditions(conditions).OrderConditions(orderConditions).Pager(pageIndex, pageSize, out itemcount).ToList();
  4. }

你需要构建相关的查询排序集合类就行了 如下:

  1. List<UosoConditions> uosoConditions = new List<UosoConditions>() {
  2. new UosoConditions { Key = "UserName", Operator = UosoOperatorEnum.Contains, Value = "1,3", ValueType = "string" }
  3. };
  4. List<UosoOrderConditions> orderConditions = new List<UosoOrderConditions> {
  5. new UosoOrderConditions{
  6. Key="UserName",
  7. Order = OrderSequence.DESC
  8. },
  9. new UosoOrderConditions{
  10. Key="PhoneNumber",
  11. Order = OrderSequence.DESC
  12. }
  13. };
  1. int itemcount = ;
  2. var list = _userServices.GetPagedList2(uosoConditions, orderConditions, pageindex, pagesize, out itemcount);

第五步:结合前端分页样式实现整体(之前的有介绍)

  1. ViewBag.Option = new UosoPagerOption()
  2. {
  3. ItemCount = itemcount,
  4. PageSize = pagesize,
  5. PageIndex = pageindex,
  6. CountNum = ,
  7. Url = Request.Path.Value,
  8. Query = Request.Query
  9. };

以上是实现分页的全部过程,这里值得注意的是 在 like查询 Contains的时候,在.NetCore中需要如下这样写,不然可能会出现反射多次被实例化的问题

  1. typeof(string).GetMethod("Contains",new Type[] { typeof(string) })

如果是.Net Framework 中 为如下方式

  1. typeof(string).GetMethod("Contains")

.NetCore 使用 Linq 动态拼接Expression表达式条件来实现 对EF、EF Core 扩展查询排序操作的更多相关文章

  1. 分享动态拼接Expression表达式组件及原理

    前言 LINQ大家都知道,用起来也还不错,但有一个问题,当你用Linq进行搜索的时候,你是这样写的 var query = from user in db.Set<User>()      ...

  2. Asp.net Core C#进行筛选、过滤、使用PredicateBuilder进行动态拼接lamdba表达式树并用作条件精准查询,模糊查询

    在asp.net core.asp.net 中做where条件过滤筛选的时候写的长而繁琐不利于维护,用PredicateBuilder进行筛选.过滤.LInq配合Ef.core进行动态拼接lamdba ...

  3. 动态拼接lambda表达式树

    前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...

  4. 用PredicateBuilder实现Linq动态拼接查询

    在使用Linq查询的时候,特别是如果你在使用Entiry Framwork,有时会遇到动态查询的情况(客户的查询条件是不固定的拼接查询).我们能想到的第一方案应该是拼接SQL,的确这样是可以达到我们的 ...

  5. 【转】EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句

    传统的操作数据库方式,筛选数据需要用StringBuilder拼接一大堆的WHERE子句. 在Entity Framework中,代码稍有不慎就会造成巨大性能消耗,如: using(var db=ne ...

  6. Lambda表达式动态拼接(备忘)

    EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句 分类: C# Lambda/Linq Entity Framework 2013-05-24 06:58 ...

  7. 表达式树动态拼接lambda

    动态拼接lambda表达式树   前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dappe ...

  8. 动态拼接表达式——Expression

    我们在项目中会遇到以下查询需求吗? 比如需要查询出满足以下条件的会员: 条件组一:30-40岁的男性会员 条件组二:20-30岁的女性会员 条件组三:60-80岁性别未知的会员 条件组内是并且关系,但 ...

  9. linq里lambda写的join查询,并附加动态拼接的条件,条件为enum类型的查询

    因为查询条件不固定的原因,sql式的linq查询没法动态拼接条件. 网上搜的资料整理之后终于解决. 参考资料: enum使用 http://blog.csdn.net/slowlifes/articl ...

随机推荐

  1. java 枚举 封装操作方法

    前言: 由于刚转java项目,所以对于java语言比较陌生,尤其是lambda和一些诸如(一个java文件只能有一个public class)等等的零散知识点之类... 使我觉得就语言的层级来说..n ...

  2. mysql账户添加远程访问

    我们要将root账户设置为远程可访问 mysql> show databases; +--------------------+ | Database | +------------------ ...

  3. Nginx多进程高并发、低时延、高可靠机制在缓存代理中的应用

    1. 开发背景 现有开源缓存代理中间件有twemproxy.codis等,其中twemproxy为单进程单线程模型,只支持memcache单机版和redis单机版,都不支持集群版功能. 由于twemp ...

  4. Elastic-Job-Lite 源码分析 —— 运维平台

    本文基于 Elastic-Job V2.1.5 版本分享 1. 概述 2. Maven模块 elastic-job-common-restful 3. Maven模块 elastic-job-cons ...

  5. System.gc()与Runtime.gc()的区别

    (1) GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象 ...

  6. 【模板】MST(Prim)

    代码如下 #include <bits/stdc++.h> using namespace std; const int maxv=2e5+10; const int maxe=5e5+1 ...

  7. 引用EChart和Bootstrap

    1.怎么引用Echart 下载之后,写一个html,里面这样写 <!DOCTYPE html> <html> <head> <meta charset=&qu ...

  8. My latest news

    2018.04.12  0:01 本站点停止更新,启用0x7c00.vip站点. 2018.03.23 复试报道(心态不太平稳).每一行的深入都是需要知识的积累和时间的沉淀,就像学法律.计算机等等.愿 ...

  9. JavaScript的单线程性质以及定时器的工作原理

    前些日子还在网上争论过js动画用setTimeout还是setInterval,个人偏向于setTimeout,当动画中牵扯到ajax时用setInterval会有时间偏差,出现一些问题即使用clea ...

  10. Spring Mvc 一个接口多个继承; (八)

    在 spring 注解实现里,一个接口一般是不能多继承的! 除非在 bean 配置文件里有 针对这个 实现类的配置: <beans:bean id="icService" c ...