我正在使用asp.net MVC 5构建一个应用程序,并使用IPagedList.MVC版本4.5.0.0,AutoMapper和Entity Framework构建一个网格。
在项目中,我有一个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知道总大小?
答案 0 :(得分:3)
我最后再看了一下IPageList.MVC,看到作者发布了这个: https://github.com/troygoode/pagedlist#example-2-manual-paging
“在某些情况下,您无法访问能够创建IQueryable的内容,例如使用.Net的内置MembershipProvider的GetAllUsers方法时。此方法提供分页,但不是通过IQueryable。幸运的是PagedList仍然有你的背(注意)使用StaticPagedList):“
我转而使用StaticPagedList,现在效果更好,只需抓取我想要的记录数量,并且分页也能正常工作。
答案 1 :(得分:1)
这是因为您正在检索所有项目。在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)
{
....
}
答案 2 :(得分:0)
我没有使用自动播放器,只有valueinjecter
。
我所做的是“映射”IList<TModel>
到IList<TViewModel>
然后你就没有代码了。它会更干净。
PagedList
不知道TEntity
,它只是分页。不要忘记分页是懒惰的。
使用Valueinjecter
我有以下代码:
https://github.com/fatagun/NetCollab/blob/master/NetCollab.Web/Mappers/Mapper.cs
答案 3 :(得分:0)
我认为你需要的是AutoMapper Queryable-Extensions。
当您使用IEnumerable<T>
接口时,实现了下划线实体查询。
因此,在ToPagedList&#34;采取&#34;之前,查询将在整个表中运行。和&#34;跳过&#34;一些页面。相反,您必须使用IQueryable<T>
变体。
当使用ORM(如NHibernate或Entity Framework)和AutoMapper的标准Mapper.Map函数时,您可能会注意到当AutoMapper尝试映射时,ORM将查询图形中所有对象的所有字段结果到目的地类型