一、前言
前面我們知道了表達(dá)樹的基本知識(shí),也明白了怎么遍歷和修改一個(gè)表達(dá)式,這里我們就一個(gè)實(shí)際的場景來進(jìn)行功能開發(fā)。
表達(dá)式系列目錄
C# 表達(dá)式樹講解(一) <https://www.cnblogs.com/snailblog/p/11521043.html>
C# 表達(dá)式樹遍歷(二) <https://www.cnblogs.com/snailblog/p/11521335.html>
C# 表達(dá)式樹分頁擴(kuò)展(三)
C# 表達(dá)式樹Lambda擴(kuò)展(四) <https://www.cnblogs.com/snailblog/p/11525118.html>
二、分頁擴(kuò)展
在實(shí)際的開發(fā)中,肯定會(huì)遇到這樣的應(yīng)用場景,一個(gè)數(shù)據(jù)源需要在頁面上進(jìn)行分頁顯示,并且頁面上需要對(duì)該數(shù)據(jù)源有一個(gè)排名。本來分頁可以在數(shù)據(jù)庫層面完成,但是因?yàn)檫@里有一個(gè)排名功能,所謂的排名,就是需要查詢出所有滿足條件的數(shù)據(jù),然后按照某個(gè)算法升序或者降序排列,然后按照進(jìn)行排名。排名之后,然后根據(jù)分頁信息,將當(dāng)前頁的數(shù)據(jù)返回給頁面,當(dāng)然中間還有自定義排序的因素。
怎么取數(shù)據(jù)源和怎么排序,這里先不做介紹,我們就實(shí)現(xiàn)對(duì)一個(gè)數(shù)據(jù)源分頁的功能。
我們先定義好分頁的實(shí)體對(duì)象
分頁請(qǐng)求對(duì)象PageRequest.cs,因?yàn)樵凇綩RM之Dapper運(yùn)用
<https://www.cnblogs.com/snailblog/p/11516315.html>】已經(jīng)說明,所以這里我就只粘貼處代碼
public class PageRequest { /// <summary> /// 每頁條數(shù) /// </summary> public int
PageSize {get; set; } /// <summary> /// 當(dāng)前頁數(shù) /// </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);//默認(rèn)處理方式 } return
resultSql.ToString(); } } View Code
分頁的返回對(duì)象PageResponse.cs
/// <summary> /// 通用分頁返回 /// </summary> /// <typeparam name="T"></typeparam>
public class PageResponse<T> { /// <summary> /// 總條數(shù) /// </summary> public long
TotalCount {get; set; } /// <summary> /// 返回 /// </summary> public List<T>
Items {get; set; } /// <summary> /// 當(dāng)前頁 /// </summary> public long PageIndex {
get; set; } /// <summary> /// 每頁條數(shù) /// </summary> public long PageSize { get;
set; } /// <summary> /// 總頁數(shù) /// </summary> public long TotalPages { get; set; }
/// <summary> /// 返回篩選集合 /// </summary> public Dictionary<string, List<string>>
ResultFilter =new Dictionary<string, List<string>>(); } View Code
對(duì)數(shù)據(jù)集分頁方法的實(shí)現(xiàn)
public class PFTPage { /// <summary> /// 對(duì)數(shù)據(jù)集分頁 /// </summary> /// <typeparam
name="T">數(shù)據(jù)集對(duì)象</typeparam> /// <param name="source">數(shù)據(jù)集</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; } }
?
為了測試,我們定義一個(gè)學(xué)生課程成績的測試類
public class ScoreClass { public string CourseName { get; set; } public string
StudentName {get; set; } public decimal Score { get; set; } }
調(diào)用代碼
var datas = new List<ScoreClass>(); datas.Add(new ScoreClass { CourseName = "數(shù)學(xué)
", StudentName = "學(xué)生A", Score = 60 }); datas.Add(new ScoreClass { CourseName = "
數(shù)學(xué)", StudentName = "學(xué)生B", Score = 65 }); datas.Add(new ScoreClass { CourseName
= "數(shù)學(xué)", StudentName = "學(xué)生C", Score = 70 }); datas.Add(new ScoreClass {
CourseName = "數(shù)學(xué)", StudentName = "學(xué)生D", Score = 75 }); datas.Add(new ScoreClass
{ CourseName = "數(shù)學(xué)", StudentName = "學(xué)生E", Score = 80 }); datas.Add(new
ScoreClass { CourseName = "數(shù)學(xué)", StudentName = "學(xué)生F", Score = 81 }); datas.Add(
new ScoreClass { CourseName = "數(shù)學(xué)", StudentName = "學(xué)生G", Score = 82 });
datas.Add(new ScoreClass { CourseName = "數(shù)學(xué)", StudentName = "學(xué)生H", Score = 83
}); datas.Add(new ScoreClass { CourseName = "數(shù)學(xué)", StudentName = "學(xué)生I", Score =
84 });//按照Score降序排序取第一個(gè)(5條數(shù)據(jù)) var page = new PageRequest() { Direction= "desc",
PageIndex=1, PageSize=5, SortBy= "Score" }; var result =
PFTPage.DataPagination(datas.AsQueryable(), page); Console.WriteLine($"
分頁結(jié)果:\n{string.Join("\n", result.Items.Select(e=>$"{e.StudentName}
{e.CourseName} {e.Score}"))}");
運(yùn)行結(jié)果
<https://img2018.cnblogs.com/blog/1764554/201909/1764554-20190915111644677-47682316.png>
監(jiān)控一下result
<https://img2018.cnblogs.com/blog/1764554/201909/1764554-20190915111645486-1833326556.png>
返回的都是我們希望返回的數(shù)據(jù)。
分頁公共方法里面,就是根據(jù)PageRequest里面的內(nèi)容,動(dòng)態(tài)的生成表達(dá)式樹的查詢,然后在對(duì)數(shù)據(jù)集使用我們生成的查詢表達(dá)式樹,就返回我們想到的數(shù)據(jù)集。
三、總結(jié)
實(shí)現(xiàn)數(shù)據(jù)分頁的公共方法,在后面的遇到數(shù)據(jù)分頁的時(shí)候,就會(huì)顯得非常的方便。有沒有感覺很好玩,那么下一篇我們?cè)诶眠@些知識(shí)對(duì)Lambda表達(dá)式進(jìn)行擴(kuò)展。
熱門工具 換一換