IPagedList.MVC,设置总大小

本文关键字:设置 MVC IPagedList | 更新日期: 2023-09-27 17:59:32

我正在使用asp.net MVC 5构建一个应用程序,并有一个使用IPagedList.MVC 4.5.0.0版本、AutoMapper和实体框架的网格。

在这个项目中,我有一个BusinessLayer,这就是我的Action所要说的,因为我不希望Action方法直接与Entity Framework对话。所以我的BLL有以下方法:

        public IPagedList<ActiveContractViewModel> GetAllContracts(string regNumFilter, int page)
    {
        var lstcontractViewModel = new List<ActiveContractViewModel>();
        using (ActiveContractRepository activeContractRepos = new ActiveContractRepository(new UnitOfWork()))
        {
            var activeContractList = activeContractRepos.All.OrderByDescending(x => x.Id).Include(c => c.Contractor);
            if (regNumFilter.Trim().Length > 0)
            {
                activeContractList = activeContractRepos.All.Where(x => x.RegistrationNumber.Contains(regNumFilter)).OrderByDescending(x => x.Id).Include(c => c.Contractor);
            }
            foreach (var activeContract in activeContractList)
            {
                Mapper.CreateMap<DomainClasses.ActiveContract, ActiveContractViewModel>().ForMember(dest => dest.ContractorModel, opts => opts.MapFrom(src => new ContractorViewModel
                    {
                        Id = src.Contractor.Id,
                        Name = src.Contractor.Name,
                        ContactPerson = src.Contractor.ContactPerson,
                        Phone = src.Contractor.Phone,
                        Fax = src.Contractor.Fax,
                        Address = src.Contractor.Address,
                        VendorNumber = src.Contractor.VendorNumber,
                        FederalTaxId = src.Contractor.FederalTaxId
                    }
                ));
                Mapper.AssertConfigurationIsValid();
                lstcontractViewModel.Add(Mapper.Map<ActiveContractViewModel>(activeContract));
            }
        }
        return lstcontractViewModel.ToPagedList(page, 20);
    }

我正在将我的ActiveContract类(从Entity Framework)映射到一个模型(ActiveContractVieWModel),它运行良好,可以返回数据并进行分页。但我在调试时注意到,foreach循环也会遍历所有记录,如果我有2500条记录,它会遍历所有的记录,构建一个大列表,然后在ToPageList方法中使用。

有没有更好的方法来绕过这一点,这样我就可以建立我的模型,只填写我需要的20条记录,并让IPagedList知道总大小?

IPagedList.MVC,设置总大小

我最终查看了IPageList.MVC的更多内容,并看到作者发布了关于这一点的帖子:https://github.com/troygoode/pagedlist#example-2手动分页

"在某些情况下,您无法访问能够创建IQueryable的东西,例如使用.Net的内置MembershipProvider的GetAllUsers方法。此方法提供分页,但不能通过IQueryaable。幸运的是,PagedList仍然支持您(请注意StaticPagedList的使用):"

我改为使用StaticPagedList,它现在工作得更好了,只需要获取我想要的记录数量,分页也能工作。

这是因为您正在检索所有项目。在您的LINQ查询中,您仅通过regNumFilter 进行筛选

var activeContractList = activeContractRepos
    .All
    .OrderByDescending(x => x.Id)
    .Include(c => c.Contractor);
activeContractList = activeContractRepos
    .All
    .Where(x => x.RegistrationNumber.Contains(regNumFilter))
    .OrderByDescending(x => x.Id)
    .Include(c => c.Contractor);

要检索特定数量的行(在每页20个项目的情况下),请在迭代结果之前使用Skip()Take()

示例代码:

var activeContractList = activeContractList 
    .Skip(20 * page)
    .Take(20);
foreach (var activeContract in activeContractList)
{
    ....
}

我使用的不是automapper,而是valueinjecter

我所做的是将IList<TModel>"映射"到IList<TViewModel>,这样你就不会有代码了。它会更干净。

PagedList不知道TEntity,它只是进行寻呼。别忘了分页是懒惰的。

使用Valueinjecter,我有以下代码:

https://github.com/fatagun/NetCollab/blob/master/NetCollab.Web/Mappers/Mapper.cs

我认为您需要的是AutoMapper可查询扩展。

当您使用IEnumerable<T>接口时,下划线实体查询会具体化。因此,在ToPagedList"占用"answers"跳过"某些页面之前,查询将针对整个表运行。相反,您将不得不使用IQueryable<T>变体。

当使用带有AutoMapper标准Mapper.Map函数的ORM(如NHibernate或Entity Framework)时,您可能会注意到,当AutoMapper试图将结果映射到目标类型时,ORM将查询图中所有对象的所有字段