From 77cc8d867ce0b0c12d1c33b774e6b5a9acde066e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20K=C3=BChn?= Date: Wed, 24 Jan 2024 09:16:51 +0100 Subject: [PATCH] Added ToHashSetAsync Extension methods on IQueryable --- .../EntityFrameworkQueryableExtensions.cs | 82 ++++++++++++++++++- .../Extensions/QueryableExtensionsTest.cs | 4 + 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs b/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs index 4dcfec3611d..3dbcaed6b29 100644 --- a/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs +++ b/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs @@ -2337,6 +2337,84 @@ public static async Task ToArrayAsync( #endregion + #region ToHashSet + + /// + /// Asynchronously creates a from an by enumerating it + /// asynchronously. + /// + /// + /// + /// Multiple active operations on the same context instance are not supported. Use to ensure + /// that any asynchronous operations have completed before calling another method on this context. + /// See Avoiding DbContext threading issues for more information and examples. + /// + /// + /// See Querying data with EF Core for more information and examples. + /// + /// + /// The type of the elements of . + /// An to create a set from. + /// A to observe while waiting for the task to complete. + /// + /// A task that represents the asynchronous operation. + /// The task result contains a that contains elements from the input sequence. + /// + /// is . + /// If the is canceled. + public static async Task> ToHashSetAsync( + this IQueryable source, + CancellationToken cancellationToken = default) + { + var set = new HashSet(); + await foreach (var element in source.AsAsyncEnumerable().WithCancellation(cancellationToken).ConfigureAwait(false)) + { + set.Add(element); + } + + return set; + } + + /// + /// Asynchronously creates a from an by enumerating it + /// asynchronously. + /// + /// + /// + /// Multiple active operations on the same context instance are not supported. Use to ensure + /// that any asynchronous operations have completed before calling another method on this context. + /// See Avoiding DbContext threading issues for more information and examples. + /// + /// + /// See Querying data with EF Core for more information and examples. + /// + /// + /// The type of the elements of . + /// An to create a set from. + /// The implementation to use when comparing values in the set, or null to use the default implementation for the set type. + /// A to observe while waiting for the task to complete. + /// + /// A task that represents the asynchronous operation. + /// The task result contains a that contains elements from the input sequence. + /// + /// is . + /// If the is canceled. + public static async Task> ToHashSetAsync( + this IQueryable source, + IEqualityComparer? comparer, + CancellationToken cancellationToken = default) + { + var set = new HashSet(comparer); + await foreach (var element in source.AsAsyncEnumerable().WithCancellation(cancellationToken).ConfigureAwait(false)) + { + set.Add(element); + } + + return set; + } + + #endregion + #region Include internal static readonly MethodInfo IncludeMethodInfo @@ -2834,8 +2912,8 @@ source.Provider is EntityQueryProvider /// public static IQueryable TagWithCallSite( this IQueryable source, - [NotParameterized] [CallerFilePath] string? filePath = null, - [NotParameterized] [CallerLineNumber] int lineNumber = 0) + [NotParameterized][CallerFilePath] string? filePath = null, + [NotParameterized][CallerLineNumber] int lineNumber = 0) => source.Provider is EntityQueryProvider ? source.Provider.CreateQuery( Expression.Call( diff --git a/test/EFCore.Tests/Extensions/QueryableExtensionsTest.cs b/test/EFCore.Tests/Extensions/QueryableExtensionsTest.cs index 62e175b9f11..53ead47687f 100644 --- a/test/EFCore.Tests/Extensions/QueryableExtensionsTest.cs +++ b/test/EFCore.Tests/Extensions/QueryableExtensionsTest.cs @@ -298,6 +298,10 @@ await SourceNonAsyncEnumerableTest( () => Source().ToDictionaryAsync(e => e, e => e, ReferenceEqualityComparer.Instance)); await SourceNonAsyncEnumerableTest( () => Source().ToDictionaryAsync(e => e, e => e, ReferenceEqualityComparer.Instance, new CancellationToken())); + await SourceNonAsyncEnumerableTest(() => Source().ToHashSetAsync()); + await SourceNonAsyncEnumerableTest(() => Source().ToHashSetAsync(EqualityComparer.Default)); + await SourceNonAsyncEnumerableTest( + () => Source().ToHashSetAsync(EqualityComparer.Default, new CancellationToken())); await SourceNonAsyncEnumerableTest(() => Source().ToListAsync()); Assert.Equal(