前面咱們知道了表達樹的基本知識,也明白了怎麼遍歷和修改一個表達式,這裏咱們就一個實際的場景來進行功能開發。html
表達式系列目錄算法
C# 表達式樹講解(一)sql
C# 表達式樹遍歷(二)數據庫
C# 表達式樹分頁擴展(三)app
在實際的開發中,確定會遇到這樣的應用場景,一個數據源須要在頁面上進行分頁顯示,而且頁面上須要對該數據源有一個排名。原本分頁能夠在數據庫層面完成,可是由於這裏有一個排名功能,所謂的排名,就是須要查詢出全部知足條件的數據,而後按照某個算法升序或者降序排列,而後按照進行排名。排名以後,而後根據分頁信息,將當前頁的數據返回給頁面,固然中間還有自定義排序的因素。測試
怎麼取數據源和怎麼排序,這裏先不作介紹,咱們就實現對一個數據源分頁的功能。ui
咱們先定義好分頁的實體對象spa
分頁請求對象PageRequest.cs,由於在【ORM之Dapper運用】已經說明,因此這裏我就只粘貼處代碼code
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表達式進行擴展。