From 76da1c78a2360a3e5e4e5e26c50489be9c0c5f32 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 1 Oct 2021 14:41:52 +0200 Subject: [PATCH] Breaking change note on DbSet not implement IAsyncEnumerable Closes #3101 --- entity-framework/core/miscellaneous/async.md | 10 +++---- .../ef-core-6.0/breaking-changes.md | 27 ++++++++++++++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/entity-framework/core/miscellaneous/async.md b/entity-framework/core/miscellaneous/async.md index 11ac32a552..8d8cb812b5 100644 --- a/entity-framework/core/miscellaneous/async.md +++ b/entity-framework/core/miscellaneous/async.md @@ -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 @@ -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 , , , 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 or , 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 to your DbSet: [!code-csharp[Main](../../../samples/core/Miscellaneous/AsyncWithSystemInteractive/Program.cs#SystemInteractiveAsync)] diff --git a/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md index 9bbfe3dfe4..c71d37e71b 100644 --- a/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md @@ -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 --- @@ -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 @@ -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. + + + +### DbSet no longer implements IAsyncEnumerable + +[Tracking Issue #24041](https://github.com/dotnet/efcore/issues/24041) + +#### Old behavior + +, which is used to execute queries on DbContext, used to implement . + +#### New behavior + + no longer directly implements . + +#### Why + + was originally made to implement 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` and those defined over `IAsyncEnumerable`. 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 as an , call to explicitly cast it.