C# 表達式樹分頁擴展(三)


一、前言

前面我們知道了表達樹的基本知識,也明白了怎么遍歷和修改一個表達式,這里我們就一個實際的場景來進行功能開發。

表達式系列目錄

C# 表達式樹講解(一)

C# 表達式樹遍歷(二)

C# 表達式樹分頁擴展(三)

C# 表達式樹Lambda擴展(四)

二、分頁擴展

在實際的開發中,肯定會遇到這樣的應用場景,一個數據源需要在頁面上進行分頁顯示,並且頁面上需要對該數據源有一個排名。本來分頁可以在數據庫層面完成,但是因為這里有一個排名功能,所謂的排名,就是需要查詢出所有滿足條件的數據,然后按照某個算法升序或者降序排列,然后按照進行排名。排名之后,然后根據分頁信息,將當前頁的數據返回給頁面,當然中間還有自定義排序的因素。

怎么取數據源和怎么排序,這里先不做介紹,我們就實現對一個數據源分頁的功能。

我們先定義好分頁的實體對象

分頁請求對象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 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>>();

    }
View Code

對數據集分頁方法的實現

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}"))}");

運行結果

image

監控一下result

1568516673(1)

返回的都是我們希望返回的數據。

分頁公共方法里面,就是根據PageRequest里面的內容,動態的生成表達式樹的查詢,然后在對數據集使用我們生成的查詢表達式樹,就返回我們想到的數據集。

三、總結

實現數據分頁的公共方法,在后面的遇到數據分頁的時候,就會顯得非常的方便。有沒有感覺很好玩,那么下一篇我們在利用這些知識對Lambda表達式進行擴展。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM