From 7f09a7e5cc13e4d09a06986820dde508c476a815 Mon Sep 17 00:00:00 2001 From: Brant Burnett Date: Fri, 27 Feb 2026 11:16:33 -0500 Subject: [PATCH] Upgrade to SDK 3.9 Motivation ---------- Ensure compatibility with the modern approach to AsyncEnumerable extensions found in .NET 10. Modifications ------------- - Upgrade to the latest version of the Couchbase SDK, which uses System.Linq.Async 7.0.0 - Address deprecation of the ToEnumerable extension - Upgrade some related packages --- .../config.json | 3 +- .../Couchbase.Linq.UnitTests.csproj | 8 ++-- Src/Couchbase.Linq/Couchbase.Linq.csproj | 5 ++- .../Execution/ClusterQueryExecutor.cs | 41 ++++++++++++++++++- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Src/Couchbase.Linq.IntegrationTests/config.json b/Src/Couchbase.Linq.IntegrationTests/config.json index 9821fdc..268ca71 100644 --- a/Src/Couchbase.Linq.IntegrationTests/config.json +++ b/Src/Couchbase.Linq.IntegrationTests/config.json @@ -2,6 +2,7 @@ "couchbase": { "connectionString": "couchbase://localhost", "username": "Administrator", - "password": "password" + "password": "password", + "enableDnsSrvResolution": false } } diff --git a/Src/Couchbase.Linq.UnitTests/Couchbase.Linq.UnitTests.csproj b/Src/Couchbase.Linq.UnitTests/Couchbase.Linq.UnitTests.csproj index b862aa7..40103bf 100644 --- a/Src/Couchbase.Linq.UnitTests/Couchbase.Linq.UnitTests.csproj +++ b/Src/Couchbase.Linq.UnitTests/Couchbase.Linq.UnitTests.csproj @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/Src/Couchbase.Linq/Couchbase.Linq.csproj b/Src/Couchbase.Linq/Couchbase.Linq.csproj index 8fe535a..83dc444 100644 --- a/Src/Couchbase.Linq/Couchbase.Linq.csproj +++ b/Src/Couchbase.Linq/Couchbase.Linq.csproj @@ -15,6 +15,7 @@ netstandard2.0;net6.0;net8.0 Couchbase.Linq Couchbase.Linq + true true true @@ -33,8 +34,8 @@ - - + + diff --git a/Src/Couchbase.Linq/Execution/ClusterQueryExecutor.cs b/Src/Couchbase.Linq/Execution/ClusterQueryExecutor.cs index ce331fd..452d2c3 100644 --- a/Src/Couchbase.Linq/Execution/ClusterQueryExecutor.cs +++ b/Src/Couchbase.Linq/Execution/ClusterQueryExecutor.cs @@ -106,7 +106,46 @@ public IEnumerable ExecuteCollection(QueryModel queryModel) /// List of objects returned by the request. public IEnumerable ExecuteCollection(string statement, LinqQueryOptions queryOptions) { - return ExecuteCollectionAsync(statement, queryOptions).ToEnumerable(); + // This sync-over-async pattern is not ideal, but necessary for compatibility + var asyncEnumerable = ExecuteCollectionAsync(statement, queryOptions); + + var enumerator = asyncEnumerable.GetAsyncEnumerator(); + try + { + while (BlockingWait(enumerator.MoveNextAsync())) + { + yield return enumerator.Current; + } + } + finally + { + BlockingWait(enumerator.DisposeAsync()); + } + } + + private static void BlockingWait(ValueTask task) + { + if (task.IsCompleted) + { + // Avoid allocating a Task unnecessarily if the ValueTask is already completed + task.GetAwaiter().GetResult(); + return; + } + + // ValueTask must be converted to Task to safely await the result if it is not completed + task.AsTask().GetAwaiter().GetResult(); + } + + private static T BlockingWait(ValueTask task) + { + if (task.IsCompleted) + { + // Avoid allocating a Task unnecessarily if the ValueTask is already completed + return task.GetAwaiter().GetResult(); + } + + // ValueTask must be converted to Task to safely await the result if it is not completed + return task.AsTask().GetAwaiter().GetResult(); } public IAsyncEnumerable ExecuteCollectionAsync(QueryModel queryModel, CancellationToken cancellationToken = default)