实体通用分页
Entity generic pagination
我必须在一个 table 中查询所有行。一口气,查询太长了,我超时了。所以我想 运行 使用分页分批查询此查询。但是需要做 size
和 take
orderby。这就是问题所在,如何按通用(可能在主键上)进行排序?或者有没有办法不用 order by ?
public async Task<IEnumerable<T>> GetListBatchLoadingAsync<T>(Expression<Func<T, bool>> iWhere = null, long iSize) where T : class, IEntity
{
IQueryable<T> theQueryable = RepositoryDBContext.Set<T>();
//Where clause
if (iWhere != null)
theQueryable = theQueryable.Where(iWhere);
//batch loading
Int64 entitiesCount = await theQueryable.CountAsync();
int totalPage = (int)Math.Ceiling(decimal.Divide(entitiesCount, iSize));
//query
var result = new List<T>();
for (int a = 0; a < totalPage; a++)
result.AddRange(await theQueryable.OrderBy(x=>x. ????).Skip(TAKECOUNT * (a)).Take(TAKECOUNT).ToListAsync());
return result;
}
假设您有一个主键集(如果您使用的是 EF,则所有表上都应该有),您可以这样做:
var keyProperty = typeof(YourEntityClass).GetProperties().SingleOrDefault(p => p.IsDefined(typeof(KeyAttribute)));
这实际上会查看您的 EF 模型并选择标记为主键的列。如果您使用的是泛型,则可以将 YourEntityClass 替换为您的 T
值。您可以使用 .Name 从 keyProperty 中提取名称,并在您的 orderby 语句中使用它(例如,您可能希望使用扩展的 linq 并指定 propName + " ASC"
,或者构建一个表达式树)。
或者,您可以使用实体模型的部分 类 来拥有一个接口,例如 IExposesPrimaryKey
并实现一些 returns 主键名称的东西。
我写了一个分页扩展,可能对你有用。具体来说,我认为通用 IOrderedQuerable 说明了如何使 OrderBy 通用:
public static IPagedEntities<T> WithPaging<T>(this IOrderedQueryable<T> orderedQuery, int page, int pageSize)
{
var totalEntities = orderedQuery.Count();
var entities = orderedQuery.Skip((page * pageSize)).Take(pageSize);
return new PagedEntities<T>(page, pageSize, totalEntities, entities);
}
使用方法如下:
// base query
var query = _dbContext.SomeItems.AsQueryable();
var orderedQuery = query.OrderBy(t => t.SomeProperyToOrderBy);
// pages the results
// the WithPaging extension method requires an IOrderedQueryable
// (orderedQuery) which is produced by calling OrderBy on an IQueryable<T>
var withPaging = orderedQuery.WithPaging(yourDesiredPage, yourDesiredPageSize);
IPagedEntities 只是用一些与分页操作相关的额外元数据包装了一个 IEnumerable。它与您的问题关系不大,但为了完整起见,我将其包括在内:
public interface IPagedEntities<out T>
{
int Page { get; }
int PageSize { get; }
int TotalSize { get; }
int Pages { get; }
int NumberSkipped { get; }
int? NextPage { get; }
int? PriorPage { get; }
int FirstPage { get; }
int LastPage { get; }
bool OnFirstPage { get; }
bool OnLastPage { get; }
bool HasNextPage { get; }
bool HasPreviousPage { get; }
IEnumerable<T> Entities { get; }
}
我必须在一个 table 中查询所有行。一口气,查询太长了,我超时了。所以我想 运行 使用分页分批查询此查询。但是需要做 size
和 take
orderby。这就是问题所在,如何按通用(可能在主键上)进行排序?或者有没有办法不用 order by ?
public async Task<IEnumerable<T>> GetListBatchLoadingAsync<T>(Expression<Func<T, bool>> iWhere = null, long iSize) where T : class, IEntity
{
IQueryable<T> theQueryable = RepositoryDBContext.Set<T>();
//Where clause
if (iWhere != null)
theQueryable = theQueryable.Where(iWhere);
//batch loading
Int64 entitiesCount = await theQueryable.CountAsync();
int totalPage = (int)Math.Ceiling(decimal.Divide(entitiesCount, iSize));
//query
var result = new List<T>();
for (int a = 0; a < totalPage; a++)
result.AddRange(await theQueryable.OrderBy(x=>x. ????).Skip(TAKECOUNT * (a)).Take(TAKECOUNT).ToListAsync());
return result;
}
假设您有一个主键集(如果您使用的是 EF,则所有表上都应该有),您可以这样做:
var keyProperty = typeof(YourEntityClass).GetProperties().SingleOrDefault(p => p.IsDefined(typeof(KeyAttribute)));
这实际上会查看您的 EF 模型并选择标记为主键的列。如果您使用的是泛型,则可以将 YourEntityClass 替换为您的 T
值。您可以使用 .Name 从 keyProperty 中提取名称,并在您的 orderby 语句中使用它(例如,您可能希望使用扩展的 linq 并指定 propName + " ASC"
,或者构建一个表达式树)。
或者,您可以使用实体模型的部分 类 来拥有一个接口,例如 IExposesPrimaryKey
并实现一些 returns 主键名称的东西。
我写了一个分页扩展,可能对你有用。具体来说,我认为通用 IOrderedQuerable 说明了如何使 OrderBy 通用:
public static IPagedEntities<T> WithPaging<T>(this IOrderedQueryable<T> orderedQuery, int page, int pageSize)
{
var totalEntities = orderedQuery.Count();
var entities = orderedQuery.Skip((page * pageSize)).Take(pageSize);
return new PagedEntities<T>(page, pageSize, totalEntities, entities);
}
使用方法如下:
// base query
var query = _dbContext.SomeItems.AsQueryable();
var orderedQuery = query.OrderBy(t => t.SomeProperyToOrderBy);
// pages the results
// the WithPaging extension method requires an IOrderedQueryable
// (orderedQuery) which is produced by calling OrderBy on an IQueryable<T>
var withPaging = orderedQuery.WithPaging(yourDesiredPage, yourDesiredPageSize);
IPagedEntities 只是用一些与分页操作相关的额外元数据包装了一个 IEnumerable。它与您的问题关系不大,但为了完整起见,我将其包括在内:
public interface IPagedEntities<out T>
{
int Page { get; }
int PageSize { get; }
int TotalSize { get; }
int Pages { get; }
int NumberSkipped { get; }
int? NextPage { get; }
int? PriorPage { get; }
int FirstPage { get; }
int LastPage { get; }
bool OnFirstPage { get; }
bool OnLastPage { get; }
bool HasNextPage { get; }
bool HasPreviousPage { get; }
IEnumerable<T> Entities { get; }
}