【问题标题】:.NET MVC Linq pagination with PagedList.NET MVC Linq 分页与 PagedList
【发布时间】:2015-05-05 10:32:41
【问题描述】:

在我的 MVC 应用程序中,我使用 LINQ 从 DB 中检索数据,并使用 PagedList 进行分页。在代码块之后,我有几个问题需要帮助。

我从缓存或数据库中检索数据的功能:

public NewsPagedListDTO GetNewsFromCacheOrDB(int pageSize, int? newsID, int? page, string newsTitle, int? categoryID, int? orderByTitle, int? orderByPublisher, int? orderByDate, int? orderByCategory)
            {
            DataCache cache = new DataCache("default");
            object cacheNews = cache.Get("cacheNews");

            List<News> news = new List<News>();


            if (cacheNews == null)
            {
                news = (from n in DB.News
                        select n).ToList();

            //Only cache if no parameters was provided
            if (newsID == null && newsTitle == null && categoryID == null && orderByTitle == null && orderByPublisher == null &&
                orderByDate == null && orderByCategory == null)
                cache.Add("cacheNews", news);
            }
            }
            else
            {
                news = (List<News>)cacheNews;
            }

            if (newsID != null)
                news = news.Where(n => n.NewsID == newsID).ToList();

            if (categoryID != null)
                news = news.Where(n => n.CategoryID == categoryID).ToList();

            if (newsTitle != null)
                news = news.Where(n => n.Title == newsTitle).ToList();

            if (orderByTitle != null)
                if (orderByTitle == 0)
                    news = news.OrderBy(n => n.Title).ToList();
                else
                    news = news.OrderByDescending(n => n.Title).ToList();

            if (orderByPublisher != null)
                if (orderByPublisher == 0)
                    news = news.OrderBy(n => n.PublishedByFullName).ToList();
                else
                    news = news.OrderByDescending(n => n.PublishedByFullName).ToList();

            if (orderByDate != null)
                if (orderByDate == 0)
                    news = news.OrderByDescending(n => n.DatePublished).ToList();
                else
                    news = news.OrderBy(n => n.DatePublished).ToList();

            if (orderByCategory != null)
                if (orderByCategory == 0)
                    news = news.OrderBy(n => n.CategoryToString).ToList();
                else
                    news = news.OrderByDescending(n => n.CategoryToString).ToList();


            List<NewsDTO> newsDTO = new List<NewsDTO>();

            foreach (var item in news)
            {
                NewsDTO newsDTOtemp = new NewsDTO();

                newsDTOtemp.BlobName = item.BlobName;
                newsDTOtemp.DatePublished = item.DatePublished;
                newsDTOtemp.NewsID = item.NewsID;
                newsDTOtemp.PreviewText = item.PreviewText;
                newsDTOtemp.PublishedByEmail = item.PublishedByEmail;
                newsDTOtemp.PublishedByFullName = item.PublishedByFullName;
                newsDTOtemp.PublishedByID = item.PublishedByID;
                newsDTOtemp.Title = item.Title;
                newsDTOtemp.CategoryID = item.Category.CategoryID;
                newsDTOtemp.CategoryToString = item.Category.Name;

                newsDTO.Add(newsDTOtemp);
            }

            //Pagination
            NewsPagedListDTO newsResultDTO = new NewsPagedListDTO();
            newsResultDTO.NewsDTO = (PagedList<NewsDTO>)newsDTO.ToPagedList(page ?? 1, pageSize);

            return newsResultDTO;
        }

我认为的分页:

@Html.PagedListPager(Model.NewsPagedListDTO.NewsDTO, page => Url.Action("News", new
   {
       page,
       newsTitle = Request.QueryString["NewsTitle"],
       categoryID = Request.QueryString["categoryID"],
       orderByTitle = Request.QueryString["orderByTitle"],
       orderByPublisher = Request.QueryString["orderByPublisher"],
       orderByDate = Request.QueryString["orderByDate"],
       orderByCategory = Request.QueryString["orderByCategory"]
   }),
    new PagedListRenderOptions()
    {
        Display = PagedListDisplayMode.IfNeeded,
        MaximumPageNumbersToDisplay = 5,
        DisplayEllipsesWhenNotShowingAllPageNumbers = false,
        DisplayLinkToPreviousPage = PagedListDisplayMode.Never,
        DisplayLinkToNextPage = PagedListDisplayMode.Never,
        LinkToFirstPageFormat = String.Format("«"),
        LinkToLastPageFormat = String.Format("»")
    })

问题

  1. 这是我第一次使用 PagedList。在检索到完整结果时进行回发以更改页面有什么意义?那么客户端分页不是更好吗?目前我正在从数据库中检索所有帖子:

    news = (来自 DB.News 中的 n 选择 n).ToList();

    并在检索到数据后,使用参数进行排序..

    当然结果很容易缓存,但是..我宁愿只获取一页的数据。

  2. 如何仅使用可选参数获取当前页面的数据?我以前使用过存储过程,但我认为 PagedList 不可能。

  3. 如何在我的 LINQ 查询中为可选参数提供更简洁的代码?我不喜欢所有那些 if 语句..

【问题讨论】:

    标签: asp.net .net asp.net-mvc pagination pagedlist


    【解决方案1】:

    问题是你必须Skip items 然后Take(pageSize)

    var pagedNews = DB.News.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
    

    假设您有 5 个项目/页。

    如果您在第 1 页

    (1 - 1) * 5 = 0 所以跳过零个项目并取 5 个

    如果您在第 2 页

    (2 - 1) * 5 = 5 所以跳过 5 个项目并拿 5 个

    您的参数是Nullable,因此您可能必须在参数上设置一个默认条件,例如如果为NULL,则为PageSize = 5PageNumber = 1

    int pageSize, int? newsID, int? page
    

    编辑:

    代替:

    if (cacheNews == null)
    {
                    news = (from n in DB.News
                            select n).ToList();
    
    ...........
    }
    

    使用这个:

    // 在进行分页之前,您必须使用 OrderBy():

    // Read as Queryable()
    
    var pagedNews = DB.News.AsQueryable();
    
    // Apply OrderBy Logic
    pagedNews = pagedNews.OrderBy(); 
    
    //ApplyPagination
    pagedNews = pagedNews.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
    

    订购方式

    您不需要将 OrderBy 列作为单独的字符串传递。

    传递一个字符串,例如selectedSortBy来自视图,

    我已经创建了一个 Helper 方法:

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace Common.Helpers
    {
        public static class PaginationHelper
        {
            public static IQueryable<T> ApplyPagination<T>(IQueryable<T> source, Pagination pagination)
            {
                var sortDirection = pagination.SortDirection == SortDirectionEnum.Ascending ? "OrderBy" : "OrderByDescending";
                var orderBy = pagination.SortBy ?? pagination.DefaultSortBy;
    
                return source.OrderBy(orderBy, sortDirection).Skip((pagination.PageNumber - 1) * pagination.PageSize).Take(pagination.PageSize);
            }
    
            public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, string sortDirection, params object[] values)
            {
                var type = typeof(T);
                var property = type.GetProperty(ordering);
                var parameter = Expression.Parameter(type, "p");
                var propertyAccess = Expression.MakeMemberAccess(parameter, property);
                var orderByExp = Expression.Lambda(propertyAccess, parameter);
                var resultExp = Expression.Call(typeof(Queryable), sortDirection, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
                return source.Provider.CreateQuery<T>(resultExp);
            }
        }
    }
    

    分页模型+枚举:

    namespace Common.Helpers
    {
        public class Pagination
        {
            public SortDirectionEnum SortDirection { get; set; }
            public string SortBy { get; set; }
            public int TotalRecords { get; set; }
            public int NumberOfPages { get; set; }
            public int PageSize { get; set; }
            public int PageNumber { get; set; }
    
            public string DefaultSortBy { get; set; }
    
            public string ReloadUrl { get; set; }
            public string TargetDiv { get; set; }
    
            public Pagination()
            {
    
            }
    
            public Pagination(string reloadUrl, string targetDiv, int totalRecords, int numberOfPages)
            {
                ReloadUrl = reloadUrl;
                TargetDiv = targetDiv;
                PageSize = 10;
                PageNumber = 1;
            }
        }
    
        public enum SortDirectionEnum
        {
            Ascending = 1,
            Descending = 2
        }
    }
    

    然后像这样调用您的查询:

    var items = DB.News.AsQueryable();
    
    items = PaginationHelper.ApplyPagination(items, PAGINATION_MODEL);
    

    【讨论】:

    • 嗨!分页正常工作,可以为空的 pageNumber 用 ??所以默认值为 1 所以这不是问题。我想知道的是,我不是在我的第一个查询中从数据库中检索 ALL 帖子然后排序并实现分页吗?这意味着如果我想减轻数据库的压力,分页是无用的。
    • 在此查询中: Skip((currentPage - 1) * pageSize).Take(pageSize) 您没有选择数据库中的所有值。您只选择 pageSize
    • @Reft 我已经包含了自定义排序逻辑
    • 太棒了,谢谢。当更改为可查询时,我遇到了一些问题,将缓存保存为可查询,而我在新闻中的导航属性没有获得任何数据(null)。如果您对此有所了解,请随时分享,否则请留下:)但是!在我接受你的回答之前的最后一个问题。您能否详细说明为什么您现在使用可查询而不是列表?
    • Iqueryable 会生成一个 SQL 类型的查询,最后当你调用 .tolist 时它会执行生成的 iqueryable
    猜你喜欢
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多