使用 PagedList 的 .NET MVC Linq 分页
.NET MVC Linq pagination with PagedList
在我的 MVC 应用程序中,我使用 LINQ 从数据库中检索数据并使用 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("»")
})
问题
这是我第一次使用 PagedList。当检索到完整结果时,通过回传更改页面有什么意义?那么客户端分页不是更好吗?目前我正在从数据库中检索所有帖子:
新闻=(来自DB.News中的n
select n).ToList();
获取数据后,根据参数排序..
当然结果很容易缓存但是..我宁愿只获取一页的数据。
如何使用可选参数只获取当前页面的数据?我以前为此使用过存储过程,但我认为 PagedList 不可能。
如何让我的 LINQ 查询中的可选参数代码更清晰?我不喜欢所有这些 if 语句..
问题是你必须 Skip
项然后 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 = 5
和 PageNumber = 1
int pageSize, int? newsID, int? page
编辑:
而不是:
if (cacheNews == null)
{
news = (from n in DB.News
select n).ToList();
...........
}
使用这个:
// You will have to OrderBy() before doing the pagination:
// 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
来自视图,
我创建了一个辅助方法:
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);
在我的 MVC 应用程序中,我使用 LINQ 从数据库中检索数据并使用 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("»")
})
问题
这是我第一次使用 PagedList。当检索到完整结果时,通过回传更改页面有什么意义?那么客户端分页不是更好吗?目前我正在从数据库中检索所有帖子:
新闻=(来自DB.News中的n select n).ToList();
获取数据后,根据参数排序..
当然结果很容易缓存但是..我宁愿只获取一页的数据。
如何使用可选参数只获取当前页面的数据?我以前为此使用过存储过程,但我认为 PagedList 不可能。
如何让我的 LINQ 查询中的可选参数代码更清晰?我不喜欢所有这些 if 语句..
问题是你必须 Skip
项然后 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 = 5
和 PageNumber = 1
int pageSize, int? newsID, int? page
编辑:
而不是:
if (cacheNews == null)
{
news = (from n in DB.News
select n).ToList();
...........
}
使用这个:
// You will have to OrderBy() before doing the pagination:
// 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
来自视图,
我创建了一个辅助方法:
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);