标签:
一、前言前面我们知道了表达树的基本知识,也明白了怎么遍历和修改一个表达式,这里我们就一个实际的场景来进行功能开发。
表达式系列目录
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(); } }
View Code分页的返回对象PageResponse.cs
/// <summary> /// 通用分页返回 /// </summary> /// <typeparam></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>数据集对象</typeparam> /// <param>数据集</param> /// <param>分页信息</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; } }
为了测试,我们定义一个学生课程成绩的测试类