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

一、前言

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

表达式系列目录

C# 表达式树讲解(一)

C# 表达式树遍历(二)

二、分页扩展

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

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

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

分页请求对象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();
        }
    }

分页的返回对象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>>();

    }

对数据集分页方法的实现

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($"分页结果:\n{string.Join("\n", result.Items.Select(e=>$"{e.StudentName} {e.CourseName} {e.Score}"))}");

运行结果

监控一下result

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

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

三、总结

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

原文地址:https://www.cnblogs.com/snailblog/p/11521359.html

时间: 2024-08-02 10:56:07

C# 表达式树分页扩展(三)的相关文章

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

一.前言 本来计算这篇文章在后面需要运用的时候写的,但是既然写到表达式的扩展呢,就一起写完吧. 看到这个标题就有一种疑问,Lambda表达式本来就是表达式树,还需要怎么扩展?那就看看下面的内容,你就知道了. 表达式系列目录 C# 表达式树讲解(一) C# 表达式树遍历(二) C# 表达式树分页扩展(三) 二.Lambda扩展 这里先不忙解答上面的问题,我们先看下这样一个应用场景. 一个页面的请求,里面带有一些条件查询,请求类如下 public class ScoreRequest { publi

C# 表达式树遍历(二)

一.前言 上一篇我们对表达式树有了初步的认识,这里我们将对表达式树进行遍历,只有弄清楚了他的运行原理,我们才可以对他进行定制化修改. 表达式系列目录 C# 表达式树讲解(一) C# 表达式树分页扩展(三) 二.表达式树的遍历 要查看表达式树的遍历,肯定不能直接用.Net Framework封装的方法,因为.Net Framework框架是闭源的,除了看中间语言(IL)去查看.我们就用ExpressionVisitor类查看一下他的运行原理,看了下ExpressionVisitor类,里面都是对各

C#高级编程六十六天----表达式树总结

表达式树总结 基础 表达式树提供了一个将可执行代码转换成数据的方法.如果你要在执行代码之前修改或转换此代码,那么它是很有用的.有其是当你要将C#代码----如LINQ查询表达式转换成其他代码在另一个程序----如SQL数据库里操作它. 表达式树的语法: 考虑下面简单的Lambda表达式: Func<int,int,int>function=(a,b)=>a+b; 这个语法包含三个部分: 1.一个声明 : Func<int,int,int>function 2.一个等号 : =

C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)

Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string, int> getLength = s => s.Length; 转换成表达式树的话是下面的代码: Expression<Func<string, int>> getLength = s => s.Length; 委托方面的东西前面都做了详细的介绍.我们主要学习表达

C#高级编程六十六天----表达式树总结【转】

https://blog.csdn.net/shanyongxu/article/details/47257139 表达式树总结 基础 表达式树提供了一个将可执行代码转换成数据的方法.如果你要在执行代码之前修改或转换此代码,那么它是很有用的.有其是当你要将C#代码----如LINQ查询表达式转换成其他代码在另一个程序----如SQL数据库里操作它. 表达式树的语法: 考虑下面简单的Lambda表达式: Func<int,int,int>function=(a,b)=>a+b; 这个语法包

Lind.DDD.ExpressionExtensions动态构建表达式树,实现对数据集的权限控制

Lind.DDD.ExpressionExtensions动态构建表达式树,实现对数据集的权限控制 仓储大叔好了相赠 网上2500元 跟谁学课堂 C#视频 ddd领域驱动架构设计视频 还赠送ABP视频两套 qq 2589406800 qq1399494644 qq2128543647 qq2890083872 qq3235634116 qq3381945576 qq2171713479源代码框架lind.ddd(后台管理系统,电商系统,API,SSO,xamarin,ko,各组件单元测试) 赠送

[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用

[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是时候来引用他解决问题.而本节主要目的就是使用表达式树解决实际问题. 读前必备: 本节学习前,需要掌握以下知识: A.继承 [.net 面向对象编程基础]  (12) 面向对象三大特性——继承 B.多态 [.net 面向对象编程基础]  (13) 面向对象三大特性——多态 C.抽象类 [.net 面向

转载:C#特性-表达式树

原文地址:http://www.cnblogs.com/tianfan/ 表达式树基础 刚接触LINQ的人往往觉得表达式树很不容易理解.通过这篇文章我希望大家看到它其实并不像想象中那么难.您只要有普通的LINQ知识便可以轻松理解本文. 表达式树提供一个将可执行代码转换成数据的方法.如果你要在执行代码之前修改或转换此代码,那么它是非常有价值的.尤其是当你要将C#代码----如LINQ查询表达式转换成其他代码在另一个程序----如SQL数据库里操作它. 但是我在这里颠倒顺序,在文章最后你很容易发现为

C#特性-表达式树

表达式树ExpressionTree 表达式树基础 转载需注明出处:http://www.cnblogs.com/tianfan/ 刚接触LINQ的人往往觉得表达式树很不容易理解.通过这篇文章我希望大家看到它其实并不像想象中那么难.您只要有普通的LINQ知识便可以轻松理解本文. 表达式树提供一个将可执行代码转换成数据的方法.如果你要在执行代码之前修改或转换此代码,那么它是非常有价值的.尤其是当你要将C#代码----如LINQ查询表达式转换成其他代码在另一个程序----如SQL数据库里操作它. 但