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表达式进行扩展。
C# 表达式树分页扩展(三)的更多相关文章
- C# 表达式树Lambda扩展(四)
一.前言 本来计算这篇文章在后面需要运用的时候写的,但是既然写到表达式的扩展呢,就一起写完吧. 看到这个标题就有一种疑问,Lambda表达式本来就是表达式树,还需要怎么扩展?那就看看下面的内容,你就知 ...
- C# 表达式树讲解(一)
一.前言 一直想写一篇Dpper的定制化扩展的文章,但是里面会设计到对Lambda表达式的解析,而解析Lambda表达式,就必须要知道表达式树的相关知识点.我希望能通过对各个模块的知识点或者运用能够多 ...
- C# 表达式树遍历(二)
一.前言 上一篇我们对表达式树有了初步的认识,这里我们将对表达式树进行遍历,只有弄清楚了他的运行原理,我们才可以对他进行定制化修改. 表达式系列目录 C# 表达式树讲解(一) C# 表达式树遍历(二) ...
- C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)
Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string ...
- C#编程(六十六)----------表达式树总结
表达式树总结 基础 表达式树提供了一个将可执行代码转换成数据的方法.如果你要在执行代码之前修改或转换此代码,那么它是很有用的.有其是当你要将C#代码----如LINQ查询表达式转换成其他代码在另一个程 ...
- C#高级编程六十六天----表达式树总结【转】
https://blog.csdn.net/shanyongxu/article/details/47257139 表达式树总结 基础 表达式树提供了一个将可执行代码转换成数据的方法.如果你要在执行代 ...
- Lind.DDD.ExpressionExtensions动态构建表达式树,实现对数据集的权限控制
回到目录 Lind.DDD框架里提出了对数据集的控制,某些权限的用户为某些表添加某些数据集的权限,具体实现是在一张表中存储用户ID,表名,检索字段,检索值和检索操作符,然后用户登陆后,通过自己权限来构 ...
- LinQ实战学习笔记(三) 序列,查询操作符,查询表达式,表达式树
序列 延迟查询执行 查询操作符 查询表达式 表达式树 (一) 序列 先上一段代码, 这段代码使用扩展方法实现下面的要求: 取进程列表,进行过滤(取大于10M的进程) 列表进行排序(按内存占用) 只保留 ...
- C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数
一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...
随机推荐
- virtualbox安装ubuntu16 LTS及其配置
一.下载安装VirtualBox 1. 从官网下载VirtualBox,目前版本:VirtualBox 6.0.6 for Windows hosts x86/amd64 2. 下载好之后安装Virt ...
- springboot-jsp打jar问题
[**前情提要**]最近做了一个项目,项目是springboot+jsp结构的,但是在发布生产环境的时候又需要用maven打成jar包,但是一开始的默认配置都不成功.下面的文章就是具体的解决过程. - ...
- vue中的虚拟DOM树
什么是虚拟DOM树?(Virtual DOM) 虚拟DOM树其实就是一个普通的js对象,它是用来描述一段HTML片段的 01 当页面渲染的时候Vue会创建一颗虚拟DOM树 02 ...
- 用python实现银行家算法
编制模拟银行家算法的程序,并以下面给出的例子验证所编写的程序的正确性. 进程 已占资源 最大需求数 资源种类 A B C D A B C D P0 0 0 1 2 0 0 1 2 P1 1 0 0 0 ...
- python基础--列表,元组
list1 = [1,2,3,4,5,6]list2 = ['wang','cong']# 1对列表中的元素取值(通过索引)print(list1[3]) # 4print(list2[1]) # c ...
- hadoop2.7之作业提交详解(上)
根据wordcount进行分析: import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; impo ...
- Tomcat 方式部署 Solo 博客系统总结
此篇为Tomcat部署方式,另有Docker部署方式,请参考文章<Docker 方式部署 Solo 博客系统总结> 一.环境和文件准备 服务器:购买的阿里云服务器,系统为Linux(C ...
- C语言编程入门之--第五章C语言基本运算和表达式-part3
5.3 挑几个运算符来讲 常用的运算符除了加减乘除(+-*/)外,还有如下: 注意:以下运算符之间用逗号隔开,C语言中也有逗号运算符,这里不讲逗号运算符. 1. 赋值运算符 =,+=,*= 2. 一 ...
- Mac 隐藏、显示文件;移动开发者常用路径
Mac Finder 标题显示文件完整路径 // mac Finder 标题栏显示文件夹完整路径, 把YES改为NO则是不显示 defaults write com.apple.finder _FXS ...
- Ubuntu 图形界面入门
Ubuntu 图形界面入门 一.目标 熟悉 Ubuntu 图形界面的基本使用 二..Ubuntu 的任务栏 三. 窗口操作按钮 四. 窗口菜单条