2015-06-16 25 views
2

我必須查詢一個表中的所有行。在一個鏡頭中,查詢太長,我得到一個超時。所以我想使用分頁在幾個批次中運行這個查詢。但要做sizetake orderby是必需的。這就是問題,如何通過通用(可能在主鍵上)進行訂單?或者有沒有沒有秩序的方式?實體泛型分頁

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; 
    } 

回答

0

我寫了一個可能對你有用的分頁擴展。具體來說,我認爲通用IOrderedQuerable說明了如何進行排序依據通用:

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; } 
} 
+0

謝謝你的回答。但我最大的問題是通過keyselector以通用方式設置訂單。 – Julian50

1

假設你有一個主鍵集(你應該對所有的表,如果你正在使用EF),你可以這樣做:

var keyProperty = typeof(YourEntityClass).GetProperties().SingleOrDefault(p => p.IsDefined(typeof(KeyAttribute))); 

這將主要看你的EF模型並選擇標記爲主鍵的列。如果您使用的是泛型,則可以用您的T值替換YourEntityClass。您可以使用.Name從keyProperty中取出名稱,並在orderby語句中使用該名稱(您可能想要使用擴展的linq並指定propName + " ASC"爲例,或者構建表達式樹)。

或者,您可以使用實體模型的部分類具有接口(如IExposesPrimaryKey)並實現返回主鍵名稱的內容。

+0

複合主鍵怎麼樣? – DavidG

+0

我明白你是如何檢索密鑰的propertyInfo的,但我應該如何在orderby中使用它?如何在keyselector中進行轉換? – Julian50

+0

@ Julian50:您可以從零開始構建表達式樹,或者使用[動態LINQ](https://dynamiclinq.codeplex.com/)等庫來簡化表達式。 – StriplingWarrior