【发布时间】:2011-04-06 14:26:15
【问题描述】:
编辑: 实体框架似乎是问题所在,在问题Entity Framework & Linq performance problem 中进一步讨论。
我支持一个早已离开的人编写的 PagedList(使用 linq/generics)类 - 它有 2 行性能非常差 - 在只有 2000 行的数据集上运行需要长达一分钟。
两个有问题的行是:
TotalItemCount = source.Count();
我可能可以通过将计数作为参数传递来解决这个问题。但是另一条慢的线是这个sn-p中的AddRange:
IQueryable<T> a = source.Skip<T>((index) * pageSize).Take<T>(pageSize);
AddRange(a.AsEnumerable());
我不明白为什么AddRange 这么慢或者我可以做些什么来改进它?
整个类源码列表是
public class PagedList<T> : List<T>, IPagedList<T>
{
public PagedList(IEnumerable<T> source, int index, int pageSize)
: this(source, index, pageSize, null)
{
}
public PagedList(IEnumerable<T> source, int index, int pageSize, int? totalCount)
{
Initialize(source.AsQueryable(), index, pageSize, totalCount);
}
public PagedList(IQueryable<T> source, int index, int pageSize)
: this(source, index, pageSize, null)
{
}
public PagedList(IQueryable<T> source, int index, int pageSize, int? totalCount)
{
Initialize(source, index, pageSize, totalCount);
}
#region IPagedList Members
public int PageCount { get; private set; }
public int TotalItemCount { get; private set; }
public int PageIndex { get; private set; }
public int PageNumber { get { return PageIndex + 1; } }
public int PageSize { get; private set; }
public bool HasPreviousPage { get; private set; }
public bool HasNextPage { get; private set; }
public bool IsFirstPage { get; private set; }
public bool IsLastPage { get; private set; }
#endregion
protected void Initialize(IQueryable<T> source, int index,
int pageSize, int? totalCount)
{
//### argument checking
if (index < 0)
{
throw new ArgumentOutOfRangeException("PageIndex cannot be below 0.");
}
if (pageSize < 1)
{
throw new ArgumentOutOfRangeException("PageSize cannot be less than 1.");
}
//### set source to blank list if source is null to prevent exceptions
if (source == null)
{
source = new List<T>().AsQueryable();
}
//### set properties
if (!totalCount.HasValue)
{
TotalItemCount = source.Count();
}
PageSize = pageSize;
PageIndex = index;
if (TotalItemCount > 0)
{
PageCount = (int)Math.Ceiling(TotalItemCount / (double)PageSize);
}
else
{
PageCount = 0;
}
HasPreviousPage = (PageIndex > 0);
HasNextPage = (PageIndex < (PageCount - 1));
IsFirstPage = (PageIndex <= 0);
IsLastPage = (PageIndex >= (PageCount - 1));
//### add items to internal list
if (TotalItemCount > 0)
{
IQueryable<T> a = source.Skip<T>((index) * pageSize).Take<T>(pageSize);
AddRange(a.AsEnumerable());
}
}
}
【问题讨论】:
-
数据从何而来? PS:“我不明白 AddRange 为什么这么慢”---
AddRange不慢,但是延迟的 linq 表达式评估很慢。 -
@zerkms 抱歉,它的 a.AsEnumerable() 很慢,而不是 AddRange
-
@robert 是这样调用的:
var pagedModel = new PagedList<T>(data, currentPage - 1, rowsPerPage);PagedList继承 List ,所以 AddRange与this.AddRange相同。并不是说我自己 100% 理解代码 -
好的,谢谢。我终于知道这是一个本地电话。
标签: c# linq performance entity-framework pagination