質問: EF 6では、データベースエンジンから返されるエンティティを非同期で処理したいと思います。 私は`ToListAsync()`と`ForEachAsync()`を呼び出すことができ、おそらく彼らは私が探しているものを行うことができますが、私は確信していません。私が探しているものは、2つの組み合わせだと思います。 `ToListAsync()`は、クエリ全体がデータベースエンジンから読み込まれ、エンティティに変換されるときに、このタスクを完了します。つまり、処理を開始する前にクエリ全体が戻るまで待つ必要があります。 私は`ForEachAsync()`が私が探しているものを行うかどうかを判断することはできませんが、他の場所で情報を見つけられないために仮定しているのは、 `ForEachAsync()`既に検索されたコレクションで機能し、 。 理想的なのは、 `ForEachAsync()` (または別の未知のメソッド)が、データがデータベースエンジンから取得されているときにタスクを呼び出すことです。 だから... `ForEachAsync()`実際にこれを行うのですか?もしそうでなければ、それを行う方法がありますか? これを望む理由は2つあります。 1. 大規模なクエリは、コレクション全体としてメモリに格納する必要はないため、メモリの占有スペースを節約し、メモリに制約されない大きな結果セットを処理する能力 2. データ検索の待ち時間中に各項目を処理するため、プロセス全体の期間が短くなる可能性があります **Update:**基本的に、 `DbContext`が`LoadAsync()`を呼び出したときに各エンティティの`OnEntityLoaded`ようなイベントを発生させた場合、私は必要なものすべてを達成することができました。エンティティを別のタスクプロセッサにエンキューするだけで、エンティティを効率的に処理してあらゆるI / Oレイテンシを利用できるためです。私は常に独立したタスクプロセッサを調整することができるので、エンティティの非同期処理をサポートするためにEFは必要なく、イベントを非同期にロードして起動するだけです。 **Update 2:**エンティティがロードされている`ForEachAsync()`が呼び出された場合、それはまた私が行ったことを達成するでしょう。
回答: `ForEachAsync`は、 `ToListAsync`とは異なり、すべてのアイテムを事前に取得せず、単にそのアイテムを反復できるようにします。反復は`async`自体です。 `QueryableExtensions.ForEachAsync` は `IDbAsyncEnumerable.ForEachAsync`委譲し`QueryableExtensions.ForEachAsync` これは次のとおりです。 ``` internal static async Task ForEachAsync( this IDbAsyncEnumerable source, Action action, CancellationToken cancellationToken) { DebugCheck.NotNull(source); DebugCheck.NotNull(action); cancellationToken.ThrowIfCancellationRequested(); using (var enumerator = source.GetAsyncEnumerator()) { if (await enumerator.MoveNextAsync(cancellationToken).WithCurrentCulture()) { Task moveNextTask; do { cancellationToken.ThrowIfCancellationRequested(); var current = enumerator.Current; moveNextTask = enumerator.MoveNextAsync(cancellationToken); action(current); } while (await moveNextTask.WithCurrentCulture()); } } } ``` これは、 `IEnumerable`反復がどのように行われているかを`async-await`に念頭におくことと非常によく似ていることがわかります。 `IEnumerable` 、 `GetEnumerator` 、 `IEnumerator` 、 `MoveNext`代わりに`IDbAsyncEnumerable`.aspx) 、 `GetAsyncEnumerator`.aspx) 、 `IDbAsyncEnumerator`.aspx) 、 `MoveNextAsync`.aspx)ます。 `MoveNextAsync`使用すると、必要なときに実際に非同期でアイテムを取得できます。