dotnet / dotnet/efcore

Consider implementing GetAsyncEnumerator extension method on IQueryable<T> to simplify consuming EF queries with await foreach

Open
#28,103 1 comment 8 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

In the current state of things, before you can consume an EF Core query with `await foreach`, you need to call `AsAsyncEnumerable`:

``` csharp
await foreach (var person in context.People
.Where(p => p.LastName == "Doe")
.AsAsyncEnumerable())
{
Console.WriteLine($"Here is someone: {person.FirstName} {person.LastName}");
}
```

Consuming queries asynchronously is a fundamental scenario and I think it would be better to avoid the clutter and to not require customers to discover said method.

This should just work:

``` csharp
await foreach (var person in context.People
.Where(p => p.LastName == "Doe"))
{
Console.WriteLine($"Here is someone: {person.FirstName} {person.LastName}");
}
```

Proposal:

Since C# 9.0, await foreach can pattern-match a `GetAsyncEnumerator` instance method or extension method.

EF Core took advantage of this in the fix for #24041 (thanks @roji for the reference!), but because only an instance method on `DbSet` was added, the improvement had a very limited scope.

The experience of consuming EF queries asynchronously can be simplified by defining `GetAsyncEnumerator()` as an extension method instead. The extension method would be declared on the same `Microsoft.EntityFramemeworkCore` namespace as all the other extensions for `IQueryable`.

Possible additional steps:

1. Get rid of the instance method on `DbSet` added by the fix to #24041 because it's redundant. It would be a small breaking change.
2. Define `WithCancellationToken` extension method also on `IQueryable` to simplify also those cases in which you want to provide a cancellation token.

The implementation of both `GetAsyncEnumerable` and `WithCancellationToken` extension methods would likely just try to cast the IQueryable to one of the EF Core query types and extract the `IAsyncEnumerable`.

If this is approved by triage, I am happy to give it a try.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.