Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking change note on DbSet not implement IAsyncEnumerable #3455

Merged
merged 1 commit into from
Oct 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions entity-framework/core/miscellaneous/async.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Asynchronous Programming - EF Core
description: Querying and saving data asynchronously with Entity Framework Core
author: roji
ms.date: 9/2/2020
ms.date: 10/1/2021
uid: core/miscellaneous/async
---
# Asynchronous Programming
Expand All @@ -26,19 +26,19 @@ For more information, see [the general C# asynchronous programming docs](/dotnet

## Async LINQ operators

In order to support executing LINQ queries asynchronously, EF Core provides a set of async extension methods which execute the query and return results. These counterparts to the standard, synchronous LINQ operators include ToListAsync, SingleAsync, AsAsyncEnumerable, etc.:
In order to support executing LINQ queries asynchronously, EF Core provides a set of async extension methods which execute the query and return results. These counterparts to the standard, synchronous LINQ operators include <xref:Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync%2A>, <xref:Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.SingleAsync%2A>, <xref:Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsAsyncEnumerable%2A>, etc.:

[!code-csharp[Main](../../../samples/core/Miscellaneous/Async/Program.cs#ToListAsync)]

Note that there are no async versions of some LINQ operators such as Where or OrderBy, because these only build up the LINQ expression tree and don't cause the query to be executed in the database. Only operators which cause query execution have async counterparts.
Note that there are no async versions of some LINQ operators such as <xref:System.Linq.Queryable.Where%2A> or <xref:System.Linq.Queryable.OrderBy%2A>, because these only build up the LINQ expression tree and don't cause the query to be executed in the database. Only operators which cause query execution have async counterparts.

> [!IMPORTANT]
> The EF Core async extension methods are defined in the `Microsoft.EntityFrameworkCore` namespace. This namespace must be imported for the methods to be available.

## Client-side async LINQ operators

The async LINQ operators discussed above can only be used on EF queries - you cannot use them with client-side LINQ to Objects query. To perform client-side async LINQ operations outside of EF, use the [System.Linq.Async package](https://www.nuget.org/packages/System.Linq.Async); this package can be especially useful for performing operations on the client that cannot be translated for evaluation at the server.
The async LINQ operators discussed above can only be used on EF queries - you cannot use them with client-side LINQ to Objects query. To perform client-side async LINQ operations outside of EF, use the [`System.Linq.Async` package](https://www.nuget.org/packages/System.Linq.Async); this package can be especially useful for performing operations on the client that cannot be translated for evaluation at the server.

Unfortunately, referencing System.Interactive.Async causes ambiguous invocation compilation errors on LINQ operators applied to EF's DbSets; this makes it hard to use both EF and System.Interactive.Async in the same project. To work around this issue, add AsQueryable to your DbSet:
In EF Core 6.0 and lower, referencing `System.Linq.Async` unfortunately causes ambiguous invocation compilation errors on LINQ operators applied to EF's DbSets; this makes it hard to use both EF and `System.Linq.Async` in the same project. To work around this issue, add <xref:System.Linq.Queryable.AsQueryable%2A> to your DbSet:

[!code-csharp[Main](../../../samples/core/Miscellaneous/AsyncWithSystemInteractive/Program.cs#SystemInteractiveAsync)]
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Breaking changes in EF Core 6.0 - EF Core
description: Complete list of breaking changes introduced in Entity Framework Core 6.0
author: ajcvickers
ms.date: 08/10/2021
ms.date: 10/1/2021
uid: core/what-is-new/ef-core-6.0/breaking-changes
---

Expand All @@ -16,6 +16,7 @@ The following API and behavior changes have the potential to break existing appl
|:--------------------------------------------------------------------------------------------------------------------------------------|------------|
| [Cleaned up mapping between DeleteBehavior and ON DELETE values](#on-delete) | Low |
| [Removed last ORDER BY when joining for collections](#last-order-by) | Low |
| [DbSet no longer implements IAsyncEnumerable](#dbset-iasyncenumerable) | Low |

## Low-impact changes

Expand Down Expand Up @@ -103,3 +104,27 @@ Every ORDER BY imposes additional work at the database side, and the last orderi
#### Mitigations

If your application expects joined entities to be returned in a particular order, make that explicit by adding a LINQ `OrderBy` operator to your query.

<a name="dbset-iasyncenumerable"></a>

### DbSet no longer implements IAsyncEnumerable

[Tracking Issue #24041](https://github.com/dotnet/efcore/issues/24041)

#### Old behavior

<xref:Microsoft.EntityFrameworkCore.DbSet%601>, which is used to execute queries on DbContext, used to implement <xref:System.Collections.Generic.IAsyncEnumerable%601>.

#### New behavior

<xref:Microsoft.EntityFrameworkCore.DbSet%601> no longer directly implements <xref:System.Collections.Generic.IAsyncEnumerable%601>.

#### Why

<xref:Microsoft.EntityFrameworkCore.DbSet%601> was originally made to implement <xref:System.Collections.Generic.IAsyncEnumerable%601> mainly in order to allow direct enumeration on it via the `foreach` construct. Unfortunately, when a project also references [System.Linq.Async](https://www.nuget.org/packages/System.Linq.Async) in order to compose async LINQ operators client-side, this resulted in an ambiguous invocation error between the operators defined over `IQueryable<T>` and those defined over `IAsyncEnumerable<T>`. C# 9 added [extension `GetEnumerator` support for `foreach` loops](/dotnet/csharp/language-reference/proposals/csharp-9.0/extension-getenumerator), removing the original main reason to reference `IAsyncEnumerable`.

The vast majority of `DbSet` usages will continue to work as-is, since they either compose LINQ operators over `DbSet`, enumerate it directly, etc. The only usages broken are those which attempt to cast `DbSet` directly to `IAsyncEnumerable`.

#### Mitigations

If you need to refer to a <xref:Microsoft.EntityFrameworkCore.DbSet%601> as an <xref:System.Collections.Generic.IAsyncEnumerable%601>, call <xref:Microsoft.EntityFrameworkCore.DbSet%601.AsAsyncEnumerable%2A?displayProperty=nameWithType> to explicitly cast it.