前面两篇文章只写了增删改功能,并不是把查询功能遗漏了,本篇就单独来讨论分页查询。分页查询很常用,实现并不难,但是想要用起来方便舒服还是要花些心思。虽然分页查询的实现跟ABP框架并没有什么关系,但是为了延续性暂且还是放在这里了。


对于分页查询来讲,需要注意的有两点:一是查询条件的处理,用户的输入是多样化的、无法预知的,查询规则要足够灵活和简单;二是查询结果的分页处理,一般是根据当前页码和每页记录数来展示数据,要有足够快的查询效率和响应速度。

1.定义查询条件输入类

在应用层AbpDemo.Application新建用于查询输入的基类,包含过滤条件和排序规则两个属性。

    public class PagedBaseDto{/// <summary>/// 过滤条件/// </summary>public List<DataFilter> Filters { get; set; }/// <summary>/// 排序规则/// </summary>public List<DataSort> Sorts { get; set; }}

其中过滤条件为:

    public class DataFilter{public string FilterName { get; set; }public string FilterValue { get; set; }public FilterType FilterType { get; set; }public ExpressionType ExpressionType { get; set; }}public enum FilterType{String,Int,Long,Boolean}public enum ExpressionType{/// <summary>///  like/// </summary>Contains,/// <summary>/// 等于/// </summary>Equal,/// <summary>/// 小于/// </summary>LessThan,/// <summary>/// 小于等于/// </summary>LessThanOrEqual,/// <summary>/// 大于/// </summary>GreaterThan,/// <summary>/// 大于等于/// </summary>GreaterThanOrEqual}

排序方式为:

    public class DataSort{public string SortName { get; set; }public SortType SortType { get; set; }}public enum SortType{/// <summary>/// 升序/// </summary>Asc,/// <summary>/// 降序/// </summary>Desc}

2.处理查询条件并返回结果

在应用层的基类AbpDemoAppServiceBase中创建一个方法用于处理查询条件并返回结果。方法的输入参数继承了上一步的基类PagedBaseDto。

        /// <summary>/// 分页查询/// </summary>/// <param name="input"></param>/// <returns></returns>public virtual async Task<IQueryable<TEntity>> Page(TPagedInput input){IQueryable<TEntity> query = Repository.GetAll();var sourceExpression = query.Expression;//where表达式if (input.Filters != null){foreach (var filter in input.Filters){if (string.IsNullOrWhiteSpace(filter.FilterName) || string.IsNullOrWhiteSpace(filter.FilterValue)){continue;}var whereLambdaExtenstion = GetLambdaExtention(filter);sourceExpression = Expression.Call(typeof(Queryable), "Where", new Type[1] { typeof(TEntity) }, sourceExpression, Expression.Quote(whereLambdaExtenstion.GetLambda()));}}if (input.Sorts != null){ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "x");string methodAsc = "OrderBy";string methodDesc = "OrderByDescending";foreach (var sort in input.Sorts){if (string.IsNullOrWhiteSpace(sort.SortName)){continue;}MemberExpression body = Expression.PropertyOrField(parameter, sort.SortName);sourceExpression = Expression.Call(typeof(Queryable), sort.SortType == SortType.Asc ? methodAsc : methodDesc, new Type[] { typeof(TEntity), body.Type }, sourceExpression, Expression.Quote(Expression.Lambda(body, parameter)));methodAsc = "ThenBy";methodDesc = "ThenByDescending";}}query = query.Provider.Execute<IEnumerable<TEntity>>(sourceExpression).AsQueryable();//result.TotalCount = query.Count();//if (input.PageSize != -1)//{//    result.Items = query.Skip((input.PageIndex - 1) * input.PageSize).Take(input.PageSize).MapTo<IEnumerable<TEntityDto>>().ToList();//}//else//{//    result.Items = query.MapTo<IEnumerable<TEntityDto>>().ToList();//}return await Task.FromResult(query);}//Lambda表达式处理private LambdaExtention<TEntity> GetLambdaExtention(DataFilter filter){var whereLambdaExtenstion = new LambdaExtention<TEntity>();switch (filter.FilterType){case FilterType.Int:whereLambdaExtenstion.GetExpression(filter.FilterName, int.Parse(filter.FilterValue), filter.ExpressionType);break;case FilterType.Long:whereLambdaExtenstion.GetExpression(filter.FilterName, long.Parse(filter.FilterValue), filter.ExpressionType);break;case FilterType.Boolean:whereLambdaExtenstion.GetExpression(filter.FilterName, filter.FilterValue.ToUpper() == "TRUE" ? true : false, filter.ExpressionType);break;default:whereLambdaExtenstion.GetExpression(filter.FilterName, filter.FilterValue, filter.ExpressionType);break;}return whereLambdaExtenstion;}

由于ABP框架中使用的是仓储模式,仓储模式一般使用Lambda表达式或Linq语句来进行查询,因此需要将输入的查询条件转化成Lambda表达式。这个过程就需要用到Lambda表达式相关的辅助类。

    /// <summary>/// 动态Lambda构造类/// </summary>/// <typeparam name="Dto"></typeparam>public class LambdaExtention<Dto> where Dto : class{private List<Expression> m_lstExpression = null;private ParameterExpression m_Parameter = null;public LambdaExtention(){m_lstExpression = new List<Expression>();m_Parameter = Expression.Parameter(typeof(Dto), "x");}//构造表达式,存放到m_lstExpression集合里面public void GetExpression(string strPropertyName, object strValue, ExpressionType expressType){Expression expRes = null;MemberExpression member = Expression.PropertyOrField(m_Parameter, strPropertyName);if (member.Type == typeof(int?) || member.Type == typeof(int)){strValue = Convert.ToInt32(strValue);}else if (member.Type == typeof(DateTime?) || member.Type == typeof(DateTime)){strValue = Convert.ToDateTime(strValue);}if (expressType == ExpressionType.Contains){expRes = Expression.Equal(member, Expression.Constant(strValue, member.Type));}else if (expressType == ExpressionType.Equal){expRes = Expression.Equal(member, Expression.Constant(strValue, member.Type));}else if (expressType == ExpressionType.LessThan){expRes = Expression.LessThan(member, Expression.Constant(strValue, member.Type));}else if (expressType == ExpressionType.LessThanOrEqual){expRes = Expression.LessThanOrEqual(member, Expression.Constant(strValue, member.Type));}else if (expressType == ExpressionType.GreaterThan){expRes = Expression.GreaterThan(member, Expression.Constant(strValue, member.Type));}else if (expressType == ExpressionType.GreaterThanOrEqual){expRes = Expression.GreaterThanOrEqual(member, Expression.Constant(strValue, member.Type));}//return expRes;m_lstExpression.Add(expRes);}//得到Lamada表达式的Expression对象public Expression<Func<Dto, bool>> GetLambda(){Expression whereExpr = null;foreach (var expr in m_lstExpression){if (whereExpr == null) whereExpr = expr;else whereExpr = Expression.And(whereExpr, expr);}if (whereExpr == null)return null;return Expression.Lambda<Func<Dto, bool>>(whereExpr, m_Parameter);}}

3.对查询结果进行分页操作

在原有分页查询输入基类PagedBaseDto的基础上添加当前页码和每页记录数的属性。

    public class PagedBaseDto{/// <summary>/// 过滤条件/// </summary>public List<DataFilter> Filters { get; set; }/// <summary>/// 排序规则/// </summary>public List<DataSort> Sorts { get; set; }private int pageSize = 10;/// <summary>/// 每页记录数/// </summary>public int PageSize{get { return pageSize; }set { pageSize = value; }}private int pageIndex = 1;/// <summary>/// 当前页码/// </summary>public int PageIndex{get { return pageIndex; }set { pageIndex = value; }}}

而应用服务基类AbpDemoAppServiceBase中的分页查询方法就可以改为:

        /// <summary>/// 分页查询/// </summary>/// <param name="input"></param>/// <returns></returns>public virtual async Task<PagedResultDto<TEntityDto>> Page(TPagedInput input){if (input == null){return new PagedResultDto<TEntityDto>();}PagedResultDto<TEntityDto> result = new PagedResultDto<TEntityDto>();IQueryable<TEntity> query = Repository.GetAll();var sourceExpression = query.Expression;//where表达式if (input.Filters != null){foreach (var filter in input.Filters){if (string.IsNullOrWhiteSpace(filter.FilterName) || string.IsNullOrWhiteSpace(filter.FilterValue)){continue;}var whereLambdaExtenstion = GetLambdaExtention(filter);sourceExpression = Expression.Call(typeof(Queryable), "Where", new Type[1] { typeof(TEntity) }, sourceExpression, Expression.Quote(whereLambdaExtenstion.GetLambda()));}}if (input.Sorts != null){ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "x");string methodAsc = "OrderBy";string methodDesc = "OrderByDescending";foreach (var sort in input.Sorts){if (string.IsNullOrWhiteSpace(sort.SortName)){continue;}MemberExpression body = Expression.PropertyOrField(parameter, sort.SortName);sourceExpression = Expression.Call(typeof(Queryable), sort.SortType == SortType.Asc ? methodAsc : methodDesc, new Type[] { typeof(TEntity), body.Type }, sourceExpression, Expression.Quote(Expression.Lambda(body, parameter)));methodAsc = "ThenBy";methodDesc = "ThenByDescending";}}query = query.Provider.Execute<IEnumerable<TEntity>>(sourceExpression).AsQueryable();result.TotalCount = query.Count();if (input.PageSize != -1){result.Items = query.Skip((input.PageIndex - 1) * input.PageSize).Take(input.PageSize).MapTo<IEnumerable<TEntityDto>>().ToList();}else{result.Items = query.MapTo<IEnumerable<TEntityDto>>().ToList();}return await Task.FromResult(result);}

其中PagedResultDto是ABP框架自带的分页查询结果的数据结构,这里没有改动直接用了。

4.在派生类中使用分页方法

由于分页查询的方法是在基类中定义的,继承基类的派生类可以直接使用,只需要根据基类的约束条件修改下代码就行了。

应用服务接口:

    /// <summary>/// 货品管理-应用服务接口/// </summary>public interface IGoodsAppService: IAbpDemoAppServiceBase<Goods,DetailGoodsDto,string,CreateGoodsDto,UpdateGoodsDto, PagedGoodsDto>,IApplicationService{}

应用服务:

    /// <summary>/// 货品管理-应用服务/// </summary>public class GoodsAppService: AbpDemoAppServiceBase<Goods,DetailGoodsDto,string,CreateGoodsDto,UpdateGoodsDto,PagedGoodsDto>,IGoodsAppService{public GoodsAppService(IRepository<Goods,string> repository):base(repository){}}

其中新加的类PagedGoodsDto是继承于第一步创建的PagedBaseDto类。


源代码示例-Github

ABP学习实践(四)--分页查询相关推荐

  1. 强化学习实践四||价值迭代法2_动作价值

    强化学习实践四||价值迭代法2 Q(s,a) = 求和 p * (r + 折扣率 * maxQ(s_____ ,a_) ) 随机玩100步游戏,记录 (s,a,s_) : r 和 (s,a) : s ...

  2. JAVA学习之 实现分页查询

    分页是系统中常用到的功能,只要涉及到查询必定伴随而来的就是分页,之前也学习过关于分页的内容,例如在牛腩的新闻发布系统,之前学习的大部分都是使用了假分页,这次学习java,使用Oracle数据库来实现一 ...

  3. ABP学习实践(六)--领域服务与工作单元

    当业务逐渐变得复杂,涉及到的实体对象不再是一个时,通用的增删改查分页功能已经无法满足要求,就需要更高级的功能.ABP框架提供了领域服务.工作单元和其他相关功能来实现对复杂业务的处理. 1.领域服务的使 ...

  4. ABP学习实践(十六)--领域驱动设计(DDD)回顾

    ABP框架并没有实现领域驱动设计(DDD)的所有思想,但是并不妨碍用领域驱动的思想去理解ABP库框架. 1.领域驱动设计(DDD)与微服务(MicroService)的关系? 领域驱动设计(DDD)是 ...

  5. MySQL学习(四)查询

    一.group_concat()函数.把groupby的分组中字段数据组合显示出来 select s_id , GROUP_CONCAT(要显示的字段名)  from table group by 分 ...

  6. Castle ActiveRecord学习实践(8)HQL查询

    本篇来了解下Castle ActiveRecord hql 查询语句. 博客园中讲解Castle ActiveRecord 的文章已经很多了,博主就不自己写了.转载一篇TerryLee大大的文章. 摘 ...

  7. 强化学习实践四:编写通用的格子世界环境类

    gym里内置了许多好玩经典的环境用于训练一个更加智能的个体,不过这些环境类绝大多数不能用来实践前五讲的视频内容,主要是由于这些环境类的观测空间的某个维度是连续变量而不是离散变量,这是前五讲内容还未涉及 ...

  8. ABP学习实践(十二)--模块系统

    模块Module是ABP框架体系很重要的概念,不同的功能组件包括项目之间都是以模块的形式进行关联的.在ABP框架的启动过程中,模块的遍历.初始化.启动也是很重要的一环. 1.模块的定义 1.1定义 在 ...

  9. ABP学习实践(十五)--缓存使用总结

    近期在工作过程中对ABP框架的缓存功能又有了深一步的理解,做一个小小的总结. 1.关于缓存 现在相当一部分小伙伴听到缓存立刻想到Redis,反应很快,但容易进入一个误区"处理缓存就要用Red ...

最新文章

  1. python 字符串内容
  2. 知乎多场景内容匹配方案荣获CSDN AI优秀案例奖
  3. python使用matplotlib可视化使用subplots子图、subplots绘制子图并为可视化的子图添加主标题(subplots main title)
  4. URL编码以及GET和POST提交乱码解决方案
  5. 2013-10-31 《October 31st, 2013》
  6. 关于splice()方法,slice() 、split()方法讲解,reverse()方法、replace()方法
  7. SSM整合Druid数据库连接池
  8. careyshop-商城框架系统
  9. cgblib 代理接口原理_Spring5参考指南-AOP代理
  10. springcloud使用LCN分布式事务
  11. 调研 微信小程序客服功能
  12. 基于等分线性回归方法的城乡收入差距因素比较分析——以广东省为例
  13. 12306验证码识别V1.5
  14. win7系统还原点来还原系统
  15. mcgs odbc mysql_MCGS构建实时数据库.doc
  16. 基于空间直方图meanshift跟踪
  17. mong命令学习记录
  18. 记录12款MacBook Pro MC946,A1398拆主板换新喇叭的过程
  19. 欧框语言框架标准C2,雅思成绩与欧洲语言共同参考框架的对应关系
  20. 学校作业5_1字符串_文本分析与加密(头哥作业[Python])

热门文章

  1. Seneor曝光基础知识
  2. 摄像头8mm可以看多远_折叠屏、透明屏、卷曲屏、拼接屏、屏下摄像头...未来屏显的先机都在这里...
  3. Vue项目启动出现的问题及解决方法
  4. 广东二本计算机专业大学排名及分数线,2021年广东二本大学排名及分数线(完整版)...
  5. 【强化学习探索01】Win10 下gym安装
  6. 不骗你,没读这一篇,你不可能懂二分
  7. typings ~报错
  8. ubuntu在windows下的wubi安装
  9. 备案不用关闭网站的9种技巧
  10. 关于指数运算,以一有趣的应用题简单展开。