EFの新機能です。私はページングがEF 6と非同期で動作するように苦労しています。How to Increase the Performance of Entity Framework with Paging私はページングメカニズムを実装しました:How to Increase the Performance of Entity Framework with Paging、私はきれいだったと思っていました。これは非同期で動作するようになっていますが、これは問題です。記事を1としてエンティティフレームワークを使用した非同期ページング6.1.3
、私はインターフェイスを作成しました:
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);
をそれはトータルカウント= 100,000 PAGECOUNT = 200、ページ= 0、のPageSize 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);
私はすなわち
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);
krillgarの最も簡単な提案@呼び出そうとすると、私は次のエラーを取得:PageListクラスでthis.TotalCount = source.Count();
上
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.
を。
アイデア?
あなたがそれを使用していないため、あなたは 'PagedList'クラスは必要ないように見えます。また、2つの「選択」の理由は何ですか? –
@IvanStoev私はそれを使用しています。 GetLogsAsync関数の10行目で使用されています。 2つの選択については、それは良い質問です。私はここで複数の質問をしたくありませんでした。私はちょうど別のものを持ってきて、それを単純化しました。私は秒でそれをアップロードします。 – Thierry
これを使用しないと、そのクラスの目的全体である 'PagedList'を返さないということです。単純にページングされた結果が必要な場合は、単純にクエリに 'Skip' /' Take'を含めてください。例えば'().Select(...)。Skip((pageNumber - 1)* pageSize).Take(pageSize).ToListAsync();' –