MVC 5 EF 6 ViewModel(页面,排序,搜索) - 排序限制分页记录结果

时间:2016-05-24 18:33:32

标签: c# asp.net-mvc entity-framework sorting pagination

在基于ViewModel的MVC应用程序中实现分页时,我遇到了排序问题。

我之前发布的有关此应用程序的问题(除了特定的,已实施的修复程序)之外,我的代码基本保持不变。

我的代码:

MVC 5 EF 6 - How to Search a Table Using Related Table Object Criteria

在注释掉默认排序的情况下,分页最初将按预期运行,但仅在“sortOrder”参数中未指定默认排序顺序时才会发生。结果将类似于:

Initial Pagination

它显示x的第1页,我可以很好地浏览页面。但是,当我尝试排序时,第一页以外的所有记录都会退出:

Post-sort Pagination

页面下降到1,该页面上的记录现在全部都存在。如果我改变分页以显示每页50条记录,在我排序后,总共将只有50条记录,在1900左右。如果我将其更改为20,则只会有20条记录,依此类推。

问题似乎与此部分代码中的指定排序有关:

switch (sortOrder)
{
    case "PONumber_desc":
        viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.PONumber).ToPagedList(pageNumber, 5);
        break;
    case "AppropNumber":
        viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.AppropNumber).ToPagedList(pageNumber, 5);
        break;

如果我评论该代码,或避免排序,它将起作用。排序确实适用于那里的记录。如果我禁用分页,并保留排序代码,它也将正常运行。当我同时使用分页和排序功能时,我的记录正在“修剪”。

这个问题似乎与我使用带有相关表的ViewModel这一事实有关。否则,我在教程和我自己的应用程序中都取得了成功。

如何在不破坏分页和搜索或更改ViewModel方法的情况下成功对记录进行排序?我只是这样做错了吗?

更新

感谢您的回复。我尝试按照你的建议构建它(以及之前使用IEnumerable<>而不是IQueryable<>)的类似方式,但我收到错误,如

错误CS1061'IQueryable'不包含'PageCount'的定义,也没有扩展方法'PageCount'接受'IQueryable'类型的第一个参数

如果它有所不同,请使用PagedList.IPagedList<> ViewModel中的实现在我用作指南的教程中:

ASP EF MVC Tutorial

他们方便地为分页示例留出整理,并切换到应用程序的不同部分进行排序。

我尝试将代码放到位,但在'viewModel.PORequests = query.ToPagedList(pageNumber,5);'我收到错误:

无法从'PagedList.IPagedList'转换为'System.Linq.IQueryable'

这个人有一个类似的问题,但是使用教程中的代码解决了这个问题,该代码不适用于排序。

Similar Issue 1

此人有一个类似的问题,但使用静态分页列表解决了它。他片段中的大部分代码都在我的头上。

Similar Issue 2

非常感谢任何进一步的帮助。

1 个答案:

答案 0 :(得分:0)

在第一步,您将ToPagedList(pageNumber, 5)分配给viewModel.PORequests。由于在接下来的步骤中您使用该变量作为源并再次应用相同的ToPagedList,显然结果是单页。

你应该做的是使用变量动态构建查询并在最终查询上调用ToPagedList,如下所示:

// Base query
var query = db.PORequests
           .Include(i => i.POItems)
           .AsQueryable();
// Filter
if (!string.IsNullOrEmpty(poNumber))
{
    query = query.Where(s => s.PONumber.Contains(poNumber));
}
if (!string.IsNullOrEmpty(AppropNumber))
{
    query = query.Where(x => x.AppropNumber.Contains(AppropNumber));
}
if (!string.IsNullOrEmpty(ContractNumber))
{
    query = query.Where(x => x.ContractNumber.Contains(ContractNumber));
}
if (!string.IsNullOrEmpty(ItemDescription))
{
   query = query.Where(x => x.POItems.Any(i => i.Description.Contains(ItemDescription)));
}
// Sort
switch (sortOrder)
{
    case "PONumber_desc":
        query = query.OrderByDescending(s => s.PONumber);
        break;
    case "AppropNumber":
        query = query.OrderBy(s => s.AppropNumber);
        break;
    case "AppropNumber_desc":
        query = query.OrderByDescending(s => s.AppropNumber);
        break;
    case "ContractNumber":
        query = query.OrderBy(s => s.ContractNumber);
        break;
    case "ContractNumber_desc":
        query = query.OrderByDescending(s => s.ContractNumber);
        break;
    default: 
        query = query.OrderBy(s => s.PONumber);
        break;
}
// Final paginated result
viewModel.PORequests = query.ToPagedList(pageNumber, 5);