zoukankan      html  css  js  c++  java
  • C# 表达式树分页扩展(三)

    一、前言

    前面我们知道了表达树的基本知识,也明白了怎么遍历和修改一个表达式,这里我们就一个实际的场景来进行功能开发。

    表达式系列目录

    C# 表达式树讲解(一)

    C# 表达式树遍历(二)

    C# 表达式树分页扩展(三)

    C# 表达式树Lambda扩展(四)

    二、分页扩展

    在实际的开发中,肯定会遇到这样的应用场景,一个数据源需要在页面上进行分页显示,并且页面上需要对该数据源有一个排名。本来分页可以在数据库层面完成,但是因为这里有一个排名功能,所谓的排名,就是需要查询出所有满足条件的数据,然后按照某个算法升序或者降序排列,然后按照进行排名。排名之后,然后根据分页信息,将当前页的数据返回给页面,当然中间还有自定义排序的因素。

    怎么取数据源和怎么排序,这里先不做介绍,我们就实现对一个数据源分页的功能。

    我们先定义好分页的实体对象

    分页请求对象PageRequest.cs,因为在【ORM之Dapper运用】已经说明,所以这里我就只粘贴处代码

    public class PageRequest
        {
            /// <summary>
            /// 每页条数
            /// </summary>
            public int PageSize { get; set; }
    
            /// <summary>
            /// 当前页数
            /// </summary>
            public int PageIndex { get; set; }
    
            /// <summary>
            /// 排序字段
            /// </summary>
            public string SortBy { get; set; }
    
            /// <summary>
            /// 排序方式(desc、asc)
            /// </summary>
            public string Direction { get; set; }
    
            /// <summary>
            /// 获取排序sql语句
            /// </summary>
            /// <returns></returns>
            public string GetOrderBySql()
            {
                if (string.IsNullOrWhiteSpace(SortBy))
                {
                    return "";
                }
                var resultSql = new StringBuilder(" ORDER BY ");
                string dir = Direction;
                if (string.IsNullOrWhiteSpace(dir))
                {
                    dir = "ASC";
                }
                if (SortBy.Contains("&"))
                {
                    resultSql.Append("").Append(string.Join(",", SortBy.Split('&').Select(e => $" {e} {dir}").ToArray()));
                }
                else
                {
                    resultSql.Append(SortBy).Append("").Append(dir);//默认处理方式
                }
                return resultSql.ToString();
            }
        }
    View Code

    分页的返回对象PageResponse.cs

    /// <summary>
        /// 通用分页返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class PageResponse<T>
        {
            /// <summary>
            /// 总条数
            /// </summary>
            public long TotalCount { get; set; }
    
            /// <summary>
            /// 返回
            /// </summary>
            public List<T> Items { get; set; }
    
            /// <summary>
            /// 当前页
            /// </summary>
            public long PageIndex { get; set; }
    
            /// <summary>
            /// 每页条数
            /// </summary>
            public long PageSize { get; set; }
    
            /// <summary>
            /// 总页数
            /// </summary>
            public long TotalPages { get; set; }
    
            /// <summary>
            /// 返回筛选集合
            /// </summary>
            public Dictionary<string, List<string>> ResultFilter = new Dictionary<string, List<string>>();
    
        }
    View Code

    对数据集分页方法的实现

    public class PFTPage
        {
            /// <summary>
            /// 对数据集分页
            /// </summary>
            /// <typeparam name="T">数据集对象</typeparam>
            /// <param name="source">数据集</param>
            /// <param name="page">分页信息</param>
            /// <returns></returns>
            public static PageResponse<T> DataPagination<T>(IQueryable<T> source, PageRequest page) where T : class, new()
            {
                var sesultData = new PageResponse<T>();
                bool isAsc = page.Direction.ToLower() == "asc" ? true : false;
                string[] _order = page.SortBy.Split('&');
                MethodCallExpression resultExp = null;
                foreach (string item in _order)
                {
                    string _orderPart = item;
                    _orderPart = Regex.Replace(_orderPart, @"s+", "");
                    string[] _orderArry = _orderPart.Split(' ');
                    string _orderField = _orderArry[0];
                    bool sort = isAsc;
                    if (_orderArry.Length == 2)
                    {
                        isAsc = _orderArry[1].ToUpper() == "ASC" ? true : false;
                    }
                    var parameter = Expression.Parameter(typeof(T), "t");
                    var property = typeof(T).GetProperty(_orderField);
                    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                    var orderByExp = Expression.Lambda(propertyAccess, parameter);
                    resultExp = Expression.Call(typeof(Queryable), isAsc ? "OrderBy" : "OrderByDescending", new Type[] { typeof(T), property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
                }
                var tempData = source.Provider.CreateQuery<T>(resultExp);
                sesultData.PageIndex = page.PageIndex;
                sesultData.PageSize = page.PageSize;
                sesultData.TotalCount = tempData.Count();
    
                sesultData.TotalPages = sesultData.TotalCount / sesultData.PageSize;
                if (sesultData.TotalCount % sesultData.PageSize > 0)
                {
                    sesultData.TotalPages += 1;
                }
    
                sesultData.Items = tempData.Skip(page.PageSize * (page.PageIndex - 1)).Take(page.PageSize).ToList();
                return sesultData;
            }
        }

    为了测试,我们定义一个学生课程成绩的测试类

    public class ScoreClass
    {
        public string CourseName { get; set; }
        public string StudentName { get; set; }
        public decimal Score { get; set; }
    }
    

    调用代码

    var datas = new List<ScoreClass>();
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生A",
                    Score = 60
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生B",
                    Score = 65
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生C",
                    Score = 70
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生D",
                    Score = 75
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生E",
                    Score = 80
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生F",
                    Score = 81
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生G",
                    Score = 82
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生H",
                    Score = 83
                });
                datas.Add(new ScoreClass
                {
                    CourseName = "数学",
                    StudentName = "学生I",
                    Score = 84
                });
                //按照Score降序排序取第一个(5条数据)
                var page = new PageRequest()
                {
                    Direction= "desc",
                    PageIndex=1,
                    PageSize=5,
                    SortBy= "Score"
                };
                var result = PFTPage.DataPagination(datas.AsQueryable(), page);
    
                Console.WriteLine($"分页结果:
    {string.Join("
    ", result.Items.Select(e=>$"{e.StudentName} {e.CourseName} {e.Score}"))}");

    运行结果

    image

    监控一下result

    1568516673(1)

    返回的都是我们希望返回的数据。

    分页公共方法里面,就是根据PageRequest里面的内容,动态的生成表达式树的查询,然后在对数据集使用我们生成的查询表达式树,就返回我们想到的数据集。

    三、总结

    实现数据分页的公共方法,在后面的遇到数据分页的时候,就会显得非常的方便。有没有感觉很好玩,那么下一篇我们在利用这些知识对Lambda表达式进行扩展。

  • 相关阅读:
    vue-cli搭建项目结构及引用bootstrap
    万年历案例
    art-template模板渲染及其过滤器
    字符串中全角半角之间的转换
    大话主席(superslide和 touchslide)插件的使用
    JS中对URL进行转码与解码
    animate.css引入实现动画效果
    [MySQL]group by 与 having 结合函数 的统计技巧
    [HTTP] 基本认证的工作流程
    [HTTP]Etag的工作流程
  • 原文地址:https://www.cnblogs.com/snailblog/p/11521359.html
Copyright © 2011-2022 走看看