我是新來的EF,所以先進的道歉,如果事情沒有做到正確。我努力讓分頁與EF 6異步工作。異步尋呼與實體框架6.1.3
我已經按照這篇文章實現了分頁機制:How to Increase the Performance of Entity Framework with Paging,我認爲它是乾淨的並且非常重要(但也不完美),但我可以這不是異步工作,這是一個問題。
按照文章中,我創建接口:
public interface IPageList
{
int TotalCount { get; }
int PageCount { get; }
int Page { get; }
int PageSize { get; }
}
我創建的類:
public class PageList<T> : List<T>, IPageList
{
public int TotalCount { get; private set; }
public int PageCount { get; private set; }
public int Page { get; private set; }
public int PageSize { get; private set; }
public PageList(IQueryable<T> source, int page, int pageSize)
{
TotalCount = source.Count();
PageCount = GetPageCount(pageSize, TotalCount);
Page = page < 1 ? 0 : page - 1;
PageSize = pageSize;
AddRange(source.Skip(Page * PageSize).Take(PageSize).ToList());
}
private int GetPageCount(int pageSize, int totalCount)
{
if (pageSize == 0)
return 0;
var remainder = totalCount % pageSize;
return (totalCount/pageSize) + (remainder == 0 ? 0 : 1);
}
}
,最後延伸:
public static class PageListExtensions
{
public static PageList<T> ToPageList<T>(this IQueryable<T> source, int pageNumber,
int pageSize)
{
return new PageList<T>(source, pageNumber, pageSize);
}
}
所以在我的數據層,我有以下功能:
public async Task<List<LogEntity>> GetLogsAsync(int pageNumber, int pageSize)
{
using (_dbContext = new DatabaseContext())
{
var results = _dbContext.Logs.Select(l => new
{
LogId = l.LogId,
Message = l.Message,
})
.OrderBy(o => o.DateTime)
.ToPageList(pageNumber, pageSize).ToList().Select(x => new LogEntity()
{
LogId = x.LogId,
Message = x.Message,
});
return await results.AsQueryable<LogEntity>().ToListAsync();
}
}
當我運行上面,我得到:
Additional information: The source IQueryable doesn't implement IDbAsyncEnumerable. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068 .
我GOOGLE了錯誤,而我讀過許多文章,我仍然在努力得到它的工作。
任何人都可以告訴我如何解決這個問題,因爲我不知道從這個階段開始。
感謝
UPDATE-1
由於伊萬在他的評論中強調,我不認爲我需要2 Select
,所以這裏是簡化版本:
var results = _dbContext.Logs.OrderBy(o=>o.DateTime)
.ToPageList(pageNumber, pageSize).Select(l => new
{
LogId = l.LogId,
Message = l.Message,
});
仍然不排序我的異步問題。目前我正在看這篇文章,這將有望幫助:
How to return empty IQueryable in an async repository method
UPDATE-2
我想我想通了,但它仍然沒有迴應,因爲我想它喜歡是的,所以我不能100%確定它是否正確完成。我認爲當在我的WPF應用程序中交換到我的日誌選項卡時,交換將是瞬時的,但它不是!
反正這裏是我已經改變了:
public async Task<List<LogEntity>> GetLogsAsync(int pageNumber, int pageSize)
{
using (_dbContext = new DatabaseContext())
{
var results = _dbContext.Logs.OrderBy(o=>o.DateTime).ToPageList(pageNumber, pageSize).Select(l => new LogEntity
{
LogId = l.LogId,
Message = l.Message,
}).AsAsyncQueryable();
return await results.ToListAsync();
}
}
如果有的話,代碼肯定比我原來的一個簡單的。
更新-3:
當我把這種:
return new PageList<LogEntity>(_dbContext.Logs, pageNumber, pageSize);
它返回TOTALCOUNT = 100,000,頁頁次= 200,頁= 0,每頁500,但隨後引發錯誤
:當的AddRange被稱爲即An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code Additional information: The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
所以我通過調用這個固定
return new PageList<LogEntity>(_dbContext.Logs.OrderBy(o=>o.DateTime),
pageNumber, pageSize);
當我試圖打電話給@ krillgar的最簡單的建議,即
return _dbContext.Logs
.Select(l => new LogEntity // Cast here so your .ToPageList
{ // will start as the object type you want.
LogId = l.LogId,
Message = l.Message
})
.OrderBy(l => l.DateTime)
.ToPageList(pageNumber, pageSize);
我得到以下錯誤:
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code Additional information: The entity or complex type 'MyCompany.DataLayerSql.LogEntity' cannot be constructed in a LINQ to Entities query.
上的分頁類this.TotalCount = source.Count();
。
任何想法?
看起來你不需要'PagedList'類,因爲你沒有使用它。另外2個'選擇'的原因是什麼? –
@IvanStoev我正在使用它。它在GetLogsAsync函數的第10行中使用。至於2個選擇,這是一個很好的問題,我不想在這裏提出多個問題。我剛剛又做了一次,我簡化了它。我會在一秒鐘內上傳它。 – Thierry
通過不使用它,我的意思是你沒有返回這個類的全部目的'PagedList'。如果您只需要分頁結果,只需在查詢中包含「Skip」/「Take」。例如返回await _dbContext.Logs.OrderBy(o => o.DateTime).Select(...)。Skip((pageNumber - 1)* pageSize).Take(pageSize).ToListAsync();' –