Asynchronously process entities as they are returned from the database engine

async-await asynchronous c# entity-framework entity-framework-6

Question

I want to be able to asynchronously handle entities in EF 6 as the database engine returns them.

Knowing I can callToListAsync() and ForEachAsync() and while they might provide what I'm looking for, I'm not sure. I believe the combination of the two is what I am seeking.

My understanding is thatToListAsync() when the full query has been read from the database engine and transformed to entities, the process will be finished. This implies that you must wait for the results of the complete query before proceeding with processing.

I'm unable to decide ifForEachAsync() does what I'm searching for, but I'm guessing so because I can't find any information elsewhere.ForEachAsync() simply operates on a previously obtained collection, using async item processing.

The ideal situation is thatForEachAsync() The job would be called as the data was being fetched from the database engine via (or some other as-yet-unknown mechanism).

Thus, doesForEachAsync() do this in reality, and if not, is there a method to do it?

There are two reasons why I desire this:

  1. Large searches don't need to store the entire collection in memory, so there is less memory footprint and more room for processing considerably larger resultsets.
  2. Due to processing each item during the latency of data retrieval, the overall operation should take less time.

Update: In essence, if aDbContext raised a situation likeOnEntityLoaded for every organization you calledLoadAsync() I could complete everything I set out to do. Since the entities could then be processed effectively and take advantage of any I/O latency, I could simply enqueue them to a different task processor. I don't really need EF to allow asynchronous processing of the entities; I can just load each entity asynchronously, fire an event, or call a delegate. I can always tune the individual task processor.

2. Update: And ifForEachAsync() was called while the entities were loading, then that would also achieve my goal.

1
7
3/14/2015 8:47:06 PM

Accepted Answer

ForEachAsync instead ofToListAsync , which only allows you to iterate through it rather than receiving all the elements in advance. Iterations areasync itself.

QueryableExtensions.ForEachAsync representatives toIDbAsyncEnumerable.ForEachAsync what is this?:

internal static async Task ForEachAsync(
    this IDbAsyncEnumerable source, Action<object> action, CancellationToken cancellationToken)
{
    DebugCheck.NotNull(source);
    DebugCheck.NotNull(action);

    cancellationToken.ThrowIfCancellationRequested();

    using (var enumerator = source.GetAsyncEnumerator())
    {
        if (await enumerator.MoveNextAsync(cancellationToken).WithCurrentCulture())
        {
            Task<bool> moveNextTask;
            do
            {
                cancellationToken.ThrowIfCancellationRequested();
                var current = enumerator.Current;
                moveNextTask = enumerator.MoveNextAsync(cancellationToken);
                action(current);
            }
            while (await moveNextTask.WithCurrentCulture());
        }
    }
}

As you can see, it closely resembles how an iteration overIEnumerable created but withasync-await a thought in place ofIEnumerable , GetEnumerator , IEnumerator and MoveNext Zzz-48-ZZZ, Zzz-51-ZZZ, Zzz-54-ZZZ, and Zzz-57-ZZZ are the numbers.

MoveNextAsync provides for true asynchronous item retrieval when necessary.

3
3/14/2015 9:20:28 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow