From a0bd291af1979351d87343cefd5d28a1f2f0fe2b Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Wed, 10 Jun 2026 10:51:38 +0530 Subject: [PATCH 01/12] chore(deps): upgrade to .NET 10 and Microsoft.Data.SqlClient 6.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Joint runtime + driver bump that prerequisites issue #2768 (MSSQL JSON data type support). Behavior-preserving — no production logic changes. WHY BOTH BUMPS ARE REQUIRED TOGETHER ==================================== SqlDbType.Json (numeric value 35) is a BCL enum value in System.Data, added in .NET 9 and present in .NET 10. It is NOT a Microsoft.Data.SqlClient symbol — SqlClient does not get to add values to a BCL enum it does not own. On .NET 8, the SqlDbType enum stops at DateTimeOffset = 34, so Enum.TryParse("json", ignoreCase: true, out _) in TypeHelper.GetSystemTypeFromSqlDbType returns false regardless of which SqlClient version is installed. The companion feature PR for #2768 plans to add a single dictionary entry [SqlDbType.Json] = typeof(string) which simply will not compile on net8.0. Both upgrades must therefore land together as a single prerequisite. WHY .NET 10 AND NOT .NET 9 ========================== - .NET 10 is the current Long-Term Support release (Nov 2025+). - .NET 9 is Standard-Term Support, EOL May 2026. - DAB's current .NET 8 line reaches EOL November 2026. Going straight to LTS avoids a second forced upgrade inside 12 months. SCOPE OF CHANGES (NO BEHAVIOR CHANGE INTENDED) ============================================== Runtime / SDK pin: - global.json: 8.0.420 -> 10.0.301 Target framework (all 11 src/**/*.csproj): - net8.0 -> net10.0 NuGet packages (Directory.Packages.props): - Microsoft.Data.SqlClient 5.2.3 -> 6.0.2 - Microsoft.Extensions.Caching.Memory 8.0.1 -> 10.0.0 - Microsoft.Extensions.Caching.Abstractions 9.0.0 -> 10.0.0 - Microsoft.Extensions.Primitives 9.0.0 -> 10.0.0 - Microsoft.Extensions.Configuration.Binder 9.0.0 -> 10.0.0 - Microsoft.Extensions.Configuration.Json 9.0.0 -> 10.0.0 - Microsoft.Extensions.Caching.StackExchangeRedis 9.0.3 -> 10.0.0 The Microsoft.Extensions.* bumps are required because OpenTelemetry's transitive chain (Microsoft.Extensions.Logging.Configuration 10.0.0) demands Configuration.Binder >= 10.0.0 — staying on 9.0.0 produces NU1605 package-downgrade errors (warning-as-error). Service.csproj (Microsoft.NET.Sdk.Web) — drop now-redundant PackageReferences (NU1510, warning-as-error): - Microsoft.Extensions.Configuration.Binder (in shared framework) - Microsoft.Extensions.Configuration.Json (in shared framework) Azure DevOps pipelines (9 occurrences across 8 files): - UseDotNet@2 version: 8.0.x -> 10.0.x Container base images (Dockerfile): - mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0 -> 10.0-azurelinux3.0 - mcr.microsoft.com/dotnet/aspnet:8.0-cbl-mariner2.0 -> 10.0-azurelinux3.0 (cbl-mariner2.0 tag does not exist for .NET 9+; Azure Linux 3.0 is Microsoft's documented successor.) Aspire AppHost (src/Aspire.AppHost/AppHost.cs): - WithArgs("-f", "net8.0") -> WithArgs("-f", "net10.0") (mssql + pg) Build/publish scripts: - scripts/publish.ps1: $dotnetTargetFrameworks net8.0 -> net10.0 - scripts/create-manifest-file.ps1: $dotnetTargetFrameworks + hashtable keys net8.0_{rid} -> net10.0_{rid} (TODO marker: release-engineering to confirm download URLs/hashes resolve) License file rename: - external_licenses/Microsoft.Data.SqlClient.SNI.5.2.0.License.txt -> external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt - scripts/notice-generation.ps1: path updated to match - TODO marker at top of license file: contents still 5.2.0 text; release-engineering to refresh from upstream before merge. SUPPRESSED ASPDEPR008 (warning-as-error) — DELIBERATE ===================================================== ASP.NET Core 10 deprecates IWebHostBuilder / IWebHost in favor of WebApplicationBuilder / IHost. Two locations in this repo still consume the obsolete types and would block compilation under the repo's TreatWarningsAsErrors=true setting: - src/Service/Program.cs (2 sites): test-only helpers CreateWebHostBuilder + CreateWebHostFromInMemoryUpdatableConfBuilder are consumed by the existing TestServer fixture which takes IWebHostBuilder. - src/Service.Tests/Configuration/ConfigurationTests.cs (3 sites): the consumer of those helpers. Migrating from WebHost to HostBuilder/WebApplicationBuilder is a behavior-affecting refactor and explicitly OUT OF SCOPE for this no-behavior-change prerequisite PR. Suppression is added at the project level (NoWarn=ASPDEPR008 on Service.csproj + Service.Tests.csproj) with an inline TODO comment pointing at this branch and a follow-up issue link placeholder. VALIDATION ========== dotnet --version : 10.0.301 dotnet restore --nologo : 11/11 projects restored (8.05s avg) dotnet build -c Debug : 0 warnings, 0 errors, 10.32s Multi-engine test categories (MsSql, PostgreSql, MySql, CosmosDb_NoSql, DwSql) were NOT run locally; they MUST run green on the Azure DevOps multi-engine matrix before this PR merges. That matrix is the gate. NEXT STEPS BEFORE MERGE ======================= 1. Release-engineering: refresh external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt from upstream for the SNI 6.0.0 version (currently still 5.2.0 text with a TODO marker at top). 2. Release-engineering: confirm scripts/create-manifest-file.ps1 net10.0_{linux,win,osx}-x64 download URLs and SHA hashes resolve once the .NET 10 publish cycle runs. 3. Multi-engine CI matrix runs green (MsSql, PostgreSql, MySql, CosmosDb_NoSql, DwSql) — that is the merge gate. 4. File follow-up issue for ASPDEPR008 migration (WebHost -> WebApplicationBuilder / IHost) so the NoWarn suppressions can be removed in a future behavior-changing PR. --- .pipelines/cosmos-pipelines.yml | 2 +- .pipelines/dwsql-pipelines.yml | 4 ++-- .pipelines/mssql-pipelines.yml | 2 +- .pipelines/mysql-pipelines.yml | 2 +- .pipelines/pg-pipelines.yml | 2 +- .pipelines/templates/build-pipelines.yml | 2 +- .pipelines/templates/mssql-test-steps.yml | 2 +- .pipelines/templates/static-tools.yml | 2 +- Dockerfile | 4 ++-- ...osoft.Data.SqlClient.SNI.6.0.0.License.txt} | 5 +++++ global.json | 2 +- scripts/create-manifest-file.ps1 | 18 +++++++++++------- scripts/notice-generation.ps1 | 2 +- scripts/publish.ps1 | 6 +++--- src/Aspire.AppHost/AppHost.cs | 4 ++-- src/Aspire.AppHost/Aspire.AppHost.csproj | 2 +- src/Auth/Azure.DataApiBuilder.Auth.csproj | 2 +- .../Azure.DataApiBuilder.Mcp.csproj | 2 +- src/Cli.Tests/Cli.Tests.csproj | 2 +- src/Cli/Cli.csproj | 2 +- src/Config/Azure.DataApiBuilder.Config.csproj | 2 +- src/Core/Azure.DataApiBuilder.Core.csproj | 2 +- src/Directory.Packages.props | 14 +++++++------- .../Azure.DataApiBuilder.Product.csproj | 2 +- ...ataApiBuilder.Service.GraphQLBuilder.csproj | 2 +- .../Azure.DataApiBuilder.Service.Tests.csproj | 10 ++++++++-- .../Azure.DataApiBuilder.Service.csproj | 16 +++++++++++----- 27 files changed, 69 insertions(+), 48 deletions(-) rename external_licenses/{Microsoft.Data.SqlClient.SNI.5.2.0.License.txt => Microsoft.Data.SqlClient.SNI.6.0.0.License.txt} (96%) diff --git a/.pipelines/cosmos-pipelines.yml b/.pipelines/cosmos-pipelines.yml index c664879288..bb596b7702 100644 --- a/.pipelines/cosmos-pipelines.yml +++ b/.pipelines/cosmos-pipelines.yml @@ -57,7 +57,7 @@ steps: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x installationPath: $(Agent.ToolsDirectory)/dotnet - task: NuGetToolInstaller@1 diff --git a/.pipelines/dwsql-pipelines.yml b/.pipelines/dwsql-pipelines.yml index bc1e36dd6d..61f1f3ff17 100644 --- a/.pipelines/dwsql-pipelines.yml +++ b/.pipelines/dwsql-pipelines.yml @@ -50,7 +50,7 @@ jobs: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x - task: NuGetToolInstaller@1 @@ -179,7 +179,7 @@ jobs: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x - task: NuGetToolInstaller@1 diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index c11bfa133c..66321a9448 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -52,7 +52,7 @@ jobs: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x - task: NuGetToolInstaller@1 diff --git a/.pipelines/mysql-pipelines.yml b/.pipelines/mysql-pipelines.yml index e6fe59d6c0..2207509792 100644 --- a/.pipelines/mysql-pipelines.yml +++ b/.pipelines/mysql-pipelines.yml @@ -49,7 +49,7 @@ jobs: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x - task: NuGetToolInstaller@1 diff --git a/.pipelines/pg-pipelines.yml b/.pipelines/pg-pipelines.yml index 6cd223aca6..93dfafd6fc 100644 --- a/.pipelines/pg-pipelines.yml +++ b/.pipelines/pg-pipelines.yml @@ -44,7 +44,7 @@ jobs: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x - task: NuGetToolInstaller@1 diff --git a/.pipelines/templates/build-pipelines.yml b/.pipelines/templates/build-pipelines.yml index 5f166084a3..3963ff521a 100644 --- a/.pipelines/templates/build-pipelines.yml +++ b/.pipelines/templates/build-pipelines.yml @@ -57,7 +57,7 @@ steps: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x installationPath: $(Agent.ToolsDirectory)/dotnet - task: NuGetToolInstaller@1 diff --git a/.pipelines/templates/mssql-test-steps.yml b/.pipelines/templates/mssql-test-steps.yml index e834132639..96bb8e45f5 100644 --- a/.pipelines/templates/mssql-test-steps.yml +++ b/.pipelines/templates/mssql-test-steps.yml @@ -34,7 +34,7 @@ steps: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x - task: NuGetToolInstaller@1 diff --git a/.pipelines/templates/static-tools.yml b/.pipelines/templates/static-tools.yml index 14bc25764f..e24d088726 100644 --- a/.pipelines/templates/static-tools.yml +++ b/.pipelines/templates/static-tools.yml @@ -24,7 +24,7 @@ jobs: displayName: Setup .NET SDK v8.0.x inputs: packageType: sdk - version: 8.0.x + version: 10.0.x # Analyze source and build output text files for credentials - task: CredScan@3 diff --git a/Dockerfile b/Dockerfile index 21dfece640..a1532beb1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ # Version values referenced from https://hub.docker.com/_/microsoft-dotnet-aspnet -FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0-azurelinux3.0 AS build WORKDIR /src COPY [".", "./"] RUN dotnet build "./src/Service/Azure.DataApiBuilder.Service.csproj" -c Docker -o /out -r linux-x64 -FROM mcr.microsoft.com/dotnet/aspnet:8.0-cbl-mariner2.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0-azurelinux3.0 AS runtime COPY --from=build /out /App # Add default dab-config.json to /App in the image diff --git a/external_licenses/Microsoft.Data.SqlClient.SNI.5.2.0.License.txt b/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt similarity index 96% rename from external_licenses/Microsoft.Data.SqlClient.SNI.5.2.0.License.txt rename to external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt index ec940f9243..42dc7d59a9 100644 --- a/external_licenses/Microsoft.Data.SqlClient.SNI.5.2.0.License.txt +++ b/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt @@ -1,3 +1,8 @@ +[TODO prereq-PR Usr/sogh/upgrade-net10-sqlclient6: This file was renamed from +Microsoft.Data.SqlClient.SNI.5.2.0.License.txt for the SqlClient 5.2.3 -> 6.0.2 +bump. Please refresh contents from the upstream license URL for the new SNI +version 6.0.0 before merge. The body below is still the 5.2.0 text.] + MICROSOFT SOFTWARE LICENSE TERMS MICROSOFT.DATA.SQLCLIENT.SNI LIBRARY diff --git a/global.json b/global.json index df2d0ef27d..f365c8c0e0 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.420", + "version": "10.0.301", "rollForward": "latestFeature" } } diff --git a/scripts/create-manifest-file.ps1 b/scripts/create-manifest-file.ps1 index 85e1579ba4..f10a78719b 100644 --- a/scripts/create-manifest-file.ps1 +++ b/scripts/create-manifest-file.ps1 @@ -21,7 +21,11 @@ if ($isReleaseBuild -eq 'true') } # Generating hash for DAB packages -$dotnetTargetFrameworks = "net8.0" +# TODO(prereq-PR Usr/sogh/upgrade-net10-sqlclient6): String-only swap of +# net8.0 -> net10.0. Release-engineering: please confirm the +# net10.0_{linux,win,osx}-x64 download URLs and SHA hashes referenced +# downstream still resolve after the .NET 10 publish cycle runs. +$dotnetTargetFrameworks = "net10.0" $RIDs = "win-x64", "linux-x64", "osx-x64" [hashtable]$frameworkPlatformDownloadMetadata = @{} [hashtable]$frameworkPlatformFileHashMetadata = @{} @@ -62,16 +66,16 @@ $latestBlock = @' "releaseDate": "${releaseDate}", "files": { "linux-x64":{ - "url": "$($frameworkPlatformDownloadMetadata["net8.0_linux-x64"])", - "sha": "$($frameworkPlatformFileHashMetadata["net8.0_linux-x64"])" + "url": "$($frameworkPlatformDownloadMetadata["net10.0_linux-x64"])", + "sha": "$($frameworkPlatformFileHashMetadata["net10.0_linux-x64"])" }, "win-x64":{ - "url": "$($frameworkPlatformDownloadMetadata["net8.0_win-x64"])", - "sha": "$($frameworkPlatformFileHashMetadata["net8.0_win-x64"])" + "url": "$($frameworkPlatformDownloadMetadata["net10.0_win-x64"])", + "sha": "$($frameworkPlatformFileHashMetadata["net10.0_win-x64"])" }, "osx-x64":{ - "url": "$($frameworkPlatformDownloadMetadata["net8.0_osx-x64"])", - "sha": "$($frameworkPlatformFileHashMetadata["net8.0_osx-x64"])" + "url": "$($frameworkPlatformDownloadMetadata["net10.0_osx-x64"])", + "sha": "$($frameworkPlatformFileHashMetadata["net10.0_osx-x64"])" }, "nuget": { "url": "${download_url_nuget_cli}", diff --git a/scripts/notice-generation.ps1 b/scripts/notice-generation.ps1 index 3b263a4b8f..0d01e2167d 100644 --- a/scripts/notice-generation.ps1 +++ b/scripts/notice-generation.ps1 @@ -15,7 +15,7 @@ Invoke-WebRequest $chiliCreamLicenseMetadataURL -UseBasicParsing | Out-File $chiliCreamLicenseSavePath # Define the path to the license file in your repository and Read the content of the license file -$sqlClientSNILicenseFilePath = "$BuildSourcesDir/external_licenses/Microsoft.Data.SqlClient.SNI.5.2.0.License.txt" +$sqlClientSNILicenseFilePath = "$BuildSourcesDir/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt" $sqlClientSNILicense = Get-Content -Path $sqlClientSNILicenseFilePath -Raw # Replace erroneous copyright, using [System.IO.File] for better performance than Get-Content and Set-Content diff --git a/scripts/publish.ps1 b/scripts/publish.ps1 index 8716f36928..5a3d0b5b59 100644 --- a/scripts/publish.ps1 +++ b/scripts/publish.ps1 @@ -10,12 +10,12 @@ param ( ) $BuildRoot = Split-Path $PSScriptRoot -Parent -$dotnetTargetFrameworks = "net8.0" +$dotnetTargetFrameworks = "net10.0" $RIDs = "win-x64", "linux-x64", "osx-x64" # Runs dotnet publish for each target framework and RID. # Example results: -# \dotnetpublishout\publish\Release\net8.0\win-x64\dab +# \dotnetpublishout\publish\Release\net10.0\win-x64\dab if ($Package) { foreach ($targetFramework in $dotnetTargetFrameworks) @@ -30,7 +30,7 @@ if ($Package) # Zips the published output for each target framework and RID. # For example: -# \dotnetpublishout\publish\Release\net8.0\win-x64\dab_net8.0_win-x64-0.14.123-rc.zip +# \dotnetpublishout\publish\Release\net10.0\win-x64\dab_net10.0_win-x64-0.14.123-rc.zip if ($CreateZip) { foreach ($targetFramework in $dotnetTargetFrameworks) diff --git a/src/Aspire.AppHost/AppHost.cs b/src/Aspire.AppHost/AppHost.cs index 3e4e3f597c..428b75a499 100644 --- a/src/Aspire.AppHost/AppHost.cs +++ b/src/Aspire.AppHost/AppHost.cs @@ -25,7 +25,7 @@ } var mssqlService = builder.AddProject("mssql-service", "Development") - .WithArgs("-f", "net8.0") + .WithArgs("-f", "net10.0") .WithEndpoint(endpointName: "https", (e) => e.Port = 1234) .WithEndpoint(endpointName: "http", (e) => e.Port = 2345) .WithEnvironment("db-type", "mssql") @@ -65,7 +65,7 @@ } var pgService = builder.AddProject("pg-service", "Development") - .WithArgs("-f", "net8.0") + .WithArgs("-f", "net10.0") .WithEndpoint(endpointName: "https", (e) => e.Port = 1234) .WithEndpoint(endpointName: "http", (e) => e.Port = 2345) .WithEnvironment("db-type", "postgresql") diff --git a/src/Aspire.AppHost/Aspire.AppHost.csproj b/src/Aspire.AppHost/Aspire.AppHost.csproj index 79d44e51a1..d47030e64f 100644 --- a/src/Aspire.AppHost/Aspire.AppHost.csproj +++ b/src/Aspire.AppHost/Aspire.AppHost.csproj @@ -4,7 +4,7 @@ Exe - net8.0 + net10.0 enable NU1603;NU1605 enable diff --git a/src/Auth/Azure.DataApiBuilder.Auth.csproj b/src/Auth/Azure.DataApiBuilder.Auth.csproj index 9537d48834..3a34ee30c0 100644 --- a/src/Auth/Azure.DataApiBuilder.Auth.csproj +++ b/src/Auth/Azure.DataApiBuilder.Auth.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable $(BaseOutputPath)\engine diff --git a/src/Azure.DataApiBuilder.Mcp/Azure.DataApiBuilder.Mcp.csproj b/src/Azure.DataApiBuilder.Mcp/Azure.DataApiBuilder.Mcp.csproj index c1e4f9cfe4..f7c1e831ec 100644 --- a/src/Azure.DataApiBuilder.Mcp/Azure.DataApiBuilder.Mcp.csproj +++ b/src/Azure.DataApiBuilder.Mcp/Azure.DataApiBuilder.Mcp.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable diff --git a/src/Cli.Tests/Cli.Tests.csproj b/src/Cli.Tests/Cli.Tests.csproj index a8081f5250..1d9c1e83f0 100644 --- a/src/Cli.Tests/Cli.Tests.csproj +++ b/src/Cli.Tests/Cli.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable false diff --git a/src/Cli/Cli.csproj b/src/Cli/Cli.csproj index 3cacab6b4b..7ae0276a39 100644 --- a/src/Cli/Cli.csproj +++ b/src/Cli/Cli.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 Cli enable enable diff --git a/src/Config/Azure.DataApiBuilder.Config.csproj b/src/Config/Azure.DataApiBuilder.Config.csproj index 6b5bdf0955..1a6e44704d 100644 --- a/src/Config/Azure.DataApiBuilder.Config.csproj +++ b/src/Config/Azure.DataApiBuilder.Config.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable $(BaseOutputPath)\engine diff --git a/src/Core/Azure.DataApiBuilder.Core.csproj b/src/Core/Azure.DataApiBuilder.Core.csproj index 412dd316ab..3497fa516a 100644 --- a/src/Core/Azure.DataApiBuilder.Core.csproj +++ b/src/Core/Azure.DataApiBuilder.Core.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable ./nupkg diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 8bb02bc13c..a9bc031835 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -32,9 +32,9 @@ - - - + + + @@ -43,9 +43,9 @@ - - - + + + @@ -81,7 +81,7 @@ - + diff --git a/src/Product/Azure.DataApiBuilder.Product.csproj b/src/Product/Azure.DataApiBuilder.Product.csproj index a385f21a53..f2237e2fba 100644 --- a/src/Product/Azure.DataApiBuilder.Product.csproj +++ b/src/Product/Azure.DataApiBuilder.Product.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable $(BaseOutputPath)\engine diff --git a/src/Service.GraphQLBuilder/Azure.DataApiBuilder.Service.GraphQLBuilder.csproj b/src/Service.GraphQLBuilder/Azure.DataApiBuilder.Service.GraphQLBuilder.csproj index c2df983509..87c2a5637e 100644 --- a/src/Service.GraphQLBuilder/Azure.DataApiBuilder.Service.GraphQLBuilder.csproj +++ b/src/Service.GraphQLBuilder/Azure.DataApiBuilder.Service.GraphQLBuilder.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable $(BaseOutputPath)\engine diff --git a/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj b/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj index ae274a4dc2..b7f7cbb054 100644 --- a/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj +++ b/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj @@ -1,11 +1,17 @@ - net8.0 + net10.0 false disable $(BaseOutputPath)\tests - NU1603 + + NU1603;ASPDEPR008 diff --git a/src/Service/Azure.DataApiBuilder.Service.csproj b/src/Service/Azure.DataApiBuilder.Service.csproj index 2ba352c02f..eba3437571 100644 --- a/src/Service/Azure.DataApiBuilder.Service.csproj +++ b/src/Service/Azure.DataApiBuilder.Service.csproj @@ -1,12 +1,20 @@ - + - net8.0 + net10.0 Debug;Release;Docker $(BaseOutputPath)\engine win-x64;linux-x64;osx-x64 true - NU1603 + + NU1603;ASPDEPR008 @@ -64,8 +72,6 @@ - - From 1064d7ff2c780b0c05d9558e4d01555943744668 Mon Sep 17 00:00:00 2001 From: Ruben Cerna Date: Wed, 17 Jun 2026 17:29:18 -0700 Subject: [PATCH 02/12] Update SqlClient 6.1.5 --- scripts/notice-generation.ps1 | 2 +- src/Config/Azure.DataApiBuilder.Config.csproj | 1 + src/Directory.Packages.props | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/notice-generation.ps1 b/scripts/notice-generation.ps1 index 0d01e2167d..dc9303332a 100644 --- a/scripts/notice-generation.ps1 +++ b/scripts/notice-generation.ps1 @@ -15,7 +15,7 @@ Invoke-WebRequest $chiliCreamLicenseMetadataURL -UseBasicParsing | Out-File $chiliCreamLicenseSavePath # Define the path to the license file in your repository and Read the content of the license file -$sqlClientSNILicenseFilePath = "$BuildSourcesDir/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt" +$sqlClientSNILicenseFilePath = "$BuildSourcesDir/external_licenses/Microsoft.Data.SqlClient.SNI.6.1.5.License.txt" $sqlClientSNILicense = Get-Content -Path $sqlClientSNILicenseFilePath -Raw # Replace erroneous copyright, using [System.IO.File] for better performance than Get-Content and Set-Content diff --git a/src/Config/Azure.DataApiBuilder.Config.csproj b/src/Config/Azure.DataApiBuilder.Config.csproj index 1a6e44704d..0d1655df76 100644 --- a/src/Config/Azure.DataApiBuilder.Config.csproj +++ b/src/Config/Azure.DataApiBuilder.Config.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index a9bc031835..bbbcf31b08 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -43,7 +43,7 @@ - + From 96f5324b2d723f6b09c0a51ab1ba7f26af1f7781 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 11:14:39 +0530 Subject: [PATCH 03/12] Address PR review feedback and align ASP.NET Core packages to 10.x - Fix UseDotNet displayName v8.0.x -> v10.0.x across pipeline files - Replace internal branch-path TODOs with durable follow-up notes - Rename SNI license to 6.0.2 (actual runtime version) and fix notice-generation reference - Bump Microsoft.AspNetCore.{TestHost,Authorization,Authentication.JwtBearer,Mvc.Testing} to 10.0.0 --- .pipelines/cosmos-pipelines.yml | 2 +- .pipelines/dwsql-pipelines.yml | 4 ++-- .pipelines/mssql-pipelines.yml | 2 +- .pipelines/mysql-pipelines.yml | 2 +- .pipelines/pg-pipelines.yml | 2 +- .pipelines/templates/build-pipelines.yml | 2 +- .pipelines/templates/mssql-test-steps.yml | 2 +- .pipelines/templates/static-tools.yml | 2 +- ...txt => Microsoft.Data.SqlClient.SNI.6.0.2.License.txt} | 5 ----- scripts/create-manifest-file.ps1 | 7 +++---- scripts/notice-generation.ps1 | 2 +- src/Directory.Packages.props | 8 ++++---- .../Azure.DataApiBuilder.Service.Tests.csproj | 3 ++- src/Service/Azure.DataApiBuilder.Service.csproj | 6 ++++-- 14 files changed, 23 insertions(+), 26 deletions(-) rename external_licenses/{Microsoft.Data.SqlClient.SNI.6.0.0.License.txt => Microsoft.Data.SqlClient.SNI.6.0.2.License.txt} (96%) diff --git a/.pipelines/cosmos-pipelines.yml b/.pipelines/cosmos-pipelines.yml index bb596b7702..0f5a7eb427 100644 --- a/.pipelines/cosmos-pipelines.yml +++ b/.pipelines/cosmos-pipelines.yml @@ -54,7 +54,7 @@ steps: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/dwsql-pipelines.yml b/.pipelines/dwsql-pipelines.yml index 61f1f3ff17..d8fe8d0455 100644 --- a/.pipelines/dwsql-pipelines.yml +++ b/.pipelines/dwsql-pipelines.yml @@ -47,7 +47,7 @@ jobs: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x @@ -176,7 +176,7 @@ jobs: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index 66321a9448..bdfb5e37e6 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -49,7 +49,7 @@ jobs: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/mysql-pipelines.yml b/.pipelines/mysql-pipelines.yml index 2207509792..d25fbabe7c 100644 --- a/.pipelines/mysql-pipelines.yml +++ b/.pipelines/mysql-pipelines.yml @@ -46,7 +46,7 @@ jobs: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/pg-pipelines.yml b/.pipelines/pg-pipelines.yml index 93dfafd6fc..14f290ecbc 100644 --- a/.pipelines/pg-pipelines.yml +++ b/.pipelines/pg-pipelines.yml @@ -41,7 +41,7 @@ jobs: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/templates/build-pipelines.yml b/.pipelines/templates/build-pipelines.yml index 3963ff521a..e6e7ca3f13 100644 --- a/.pipelines/templates/build-pipelines.yml +++ b/.pipelines/templates/build-pipelines.yml @@ -54,7 +54,7 @@ steps: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/templates/mssql-test-steps.yml b/.pipelines/templates/mssql-test-steps.yml index 96bb8e45f5..565273f27c 100644 --- a/.pipelines/templates/mssql-test-steps.yml +++ b/.pipelines/templates/mssql-test-steps.yml @@ -31,7 +31,7 @@ steps: # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from # specifying the runtime version a project targets." - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/.pipelines/templates/static-tools.yml b/.pipelines/templates/static-tools.yml index e24d088726..20465297ea 100644 --- a/.pipelines/templates/static-tools.yml +++ b/.pipelines/templates/static-tools.yml @@ -21,7 +21,7 @@ jobs: clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x + displayName: Setup .NET SDK v10.0.x inputs: packageType: sdk version: 10.0.x diff --git a/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt b/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.2.License.txt similarity index 96% rename from external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt rename to external_licenses/Microsoft.Data.SqlClient.SNI.6.0.2.License.txt index 42dc7d59a9..ec940f9243 100644 --- a/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt +++ b/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.2.License.txt @@ -1,8 +1,3 @@ -[TODO prereq-PR Usr/sogh/upgrade-net10-sqlclient6: This file was renamed from -Microsoft.Data.SqlClient.SNI.5.2.0.License.txt for the SqlClient 5.2.3 -> 6.0.2 -bump. Please refresh contents from the upstream license URL for the new SNI -version 6.0.0 before merge. The body below is still the 5.2.0 text.] - MICROSOFT SOFTWARE LICENSE TERMS MICROSOFT.DATA.SQLCLIENT.SNI LIBRARY diff --git a/scripts/create-manifest-file.ps1 b/scripts/create-manifest-file.ps1 index f10a78719b..d2a521bdf2 100644 --- a/scripts/create-manifest-file.ps1 +++ b/scripts/create-manifest-file.ps1 @@ -21,10 +21,9 @@ if ($isReleaseBuild -eq 'true') } # Generating hash for DAB packages -# TODO(prereq-PR Usr/sogh/upgrade-net10-sqlclient6): String-only swap of -# net8.0 -> net10.0. Release-engineering: please confirm the -# net10.0_{linux,win,osx}-x64 download URLs and SHA hashes referenced -# downstream still resolve after the .NET 10 publish cycle runs. +# TODO: Release-engineering - confirm the net10.0_{linux,win,osx}-x64 download +# URLs and SHA hashes referenced downstream still resolve after the .NET 10 +# publish cycle runs. (Add a tracking issue number/link here once created.) $dotnetTargetFrameworks = "net10.0" $RIDs = "win-x64", "linux-x64", "osx-x64" [hashtable]$frameworkPlatformDownloadMetadata = @{} diff --git a/scripts/notice-generation.ps1 b/scripts/notice-generation.ps1 index dc9303332a..a7aa620bfe 100644 --- a/scripts/notice-generation.ps1 +++ b/scripts/notice-generation.ps1 @@ -15,7 +15,7 @@ Invoke-WebRequest $chiliCreamLicenseMetadataURL -UseBasicParsing | Out-File $chiliCreamLicenseSavePath # Define the path to the license file in your repository and Read the content of the license file -$sqlClientSNILicenseFilePath = "$BuildSourcesDir/external_licenses/Microsoft.Data.SqlClient.SNI.6.1.5.License.txt" +$sqlClientSNILicenseFilePath = "$BuildSourcesDir/external_licenses/Microsoft.Data.SqlClient.SNI.6.0.2.License.txt" $sqlClientSNILicense = Get-Content -Path $sqlClientSNILicenseFilePath -Raw # Replace erroneous copyright, using [System.IO.File] for better performance than Get-Content and Set-Content diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index bbbcf31b08..414e489b45 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -24,12 +24,12 @@ - - + + - - + + diff --git a/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj b/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj index b7f7cbb054..f75b61d01f 100644 --- a/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj +++ b/src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj @@ -10,7 +10,8 @@ test-only helpers. Migrating to IHost is behavior-affecting refactor work tracked separately; suppressed here so the .NET 10 + SqlClient 6.x prerequisite PR stays behavior-preserving. - TODO(prereq-PR Usr/sogh/upgrade-net10-sqlclient6): file a follow-up issue. --> + TODO: file a follow-up issue to migrate off IWebHostBuilder/IWebHost + to IHost and remove this ASPDEPR008 suppression. --> NU1603;ASPDEPR008 diff --git a/src/Service/Azure.DataApiBuilder.Service.csproj b/src/Service/Azure.DataApiBuilder.Service.csproj index eba3437571..a03f9690c0 100644 --- a/src/Service/Azure.DataApiBuilder.Service.csproj +++ b/src/Service/Azure.DataApiBuilder.Service.csproj @@ -12,8 +12,10 @@ TestServer fixture takes IWebHostBuilder. Migrating to WebApplicationBuilder/HostBuilder is behavior-affecting refactor work tracked separately; suppressed here so the .NET 10 + SqlClient - 6.x prerequisite PR stays behavior-preserving. TODO(prereq-PR - Usr/sogh/upgrade-net10-sqlclient6): file a follow-up issue. --> + 6.x prerequisite PR stays behavior-preserving. TODO: file a + follow-up issue to migrate off WebHost (IWebHostBuilder/IWebHost) + to WebApplicationBuilder/IHost and remove this ASPDEPR008 + suppression. --> NU1603;ASPDEPR008 From 280151bd2082f62f1fb20362615b6ba400eba57d Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 11:27:15 +0530 Subject: [PATCH 04/12] Pin MessagePack to 2.5.301 to fix NU1903 transitive vulnerability Aspire.Hosting pulls MessagePack 2.5.192 transitively (via KubernetesClient), which has high-severity advisory GHSA-hv8m-jj95-wg3x (CVE-2026-48109). The repo treats NU1903 as error, failing restore. Pin to patched 2.5.301 via CPM and add a direct reference in Aspire.AppHost to force the transitive upgrade. --- src/Aspire.AppHost/Aspire.AppHost.csproj | 3 +++ src/Directory.Packages.props | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Aspire.AppHost/Aspire.AppHost.csproj b/src/Aspire.AppHost/Aspire.AppHost.csproj index d47030e64f..4fbe70cdcf 100644 --- a/src/Aspire.AppHost/Aspire.AppHost.csproj +++ b/src/Aspire.AppHost/Aspire.AppHost.csproj @@ -15,6 +15,9 @@ + + diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 414e489b45..56523d0a94 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -32,6 +32,9 @@ + + From 1a7d3091583e483551baad5ffaafa71fb2cb6111 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 11:38:29 +0530 Subject: [PATCH 05/12] Formatting fixes --- .../Factories/MutationEngineFactory.cs | 3 +- .../SqlUpdateQueryStructure.cs | 30 +++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Core/Resolvers/Factories/MutationEngineFactory.cs b/src/Core/Resolvers/Factories/MutationEngineFactory.cs index 9b4df9f8bf..086559ac9d 100644 --- a/src/Core/Resolvers/Factories/MutationEngineFactory.cs +++ b/src/Core/Resolvers/Factories/MutationEngineFactory.cs @@ -107,7 +107,8 @@ public IMutationEngine GetMutationEngine(DatabaseType databaseType) $"{nameof(databaseType)}:{databaseType} could not be found within the config", HttpStatusCode.BadRequest, DataApiBuilderException.SubStatusCodes.DataSourceNotFound); - }; + } + ; return mutationEngine; } diff --git a/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs b/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs index ecbbf3fc5c..2fffa19ef5 100644 --- a/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs +++ b/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs @@ -122,26 +122,26 @@ public SqlUpdateStructure( Predicates.Add(CreatePredicateForParam(new KeyValuePair(pkBackingColumn, param.Value))); } else // Unpack the input argument type as columns to update - if (param.Key == UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME) - { - IDictionary updateFields = - GQLMutArgumentToDictParams(context, UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME, mutationParams); - - foreach (KeyValuePair field in updateFields) + if (param.Key == UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME) { - string fieldBackingColumn = field.Key; - if (sqlMetadataProvider.TryGetBackingColumn(entityName, field.Key, out string? resolvedBackingColumn) - && !string.IsNullOrWhiteSpace(resolvedBackingColumn)) - { - fieldBackingColumn = resolvedBackingColumn; - } + IDictionary updateFields = + GQLMutArgumentToDictParams(context, UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME, mutationParams); - if (columns.Contains(fieldBackingColumn)) + foreach (KeyValuePair field in updateFields) { - UpdateOperations.Add(CreatePredicateForParam(new KeyValuePair(key: fieldBackingColumn, field.Value))); + string fieldBackingColumn = field.Key; + if (sqlMetadataProvider.TryGetBackingColumn(entityName, field.Key, out string? resolvedBackingColumn) + && !string.IsNullOrWhiteSpace(resolvedBackingColumn)) + { + fieldBackingColumn = resolvedBackingColumn; + } + + if (columns.Contains(fieldBackingColumn)) + { + UpdateOperations.Add(CreatePredicateForParam(new KeyValuePair(key: fieldBackingColumn, field.Value))); + } } } - } } if (UpdateOperations.Count == 0) From a6ecbb930c202bb92cf695229270ac4e12d45edc Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 11:45:09 +0530 Subject: [PATCH 06/12] Formatting fixes --- src/Core/Resolvers/Factories/MutationEngineFactory.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/Resolvers/Factories/MutationEngineFactory.cs b/src/Core/Resolvers/Factories/MutationEngineFactory.cs index 086559ac9d..08a5fea2e3 100644 --- a/src/Core/Resolvers/Factories/MutationEngineFactory.cs +++ b/src/Core/Resolvers/Factories/MutationEngineFactory.cs @@ -108,7 +108,6 @@ public IMutationEngine GetMutationEngine(DatabaseType databaseType) HttpStatusCode.BadRequest, DataApiBuilderException.SubStatusCodes.DataSourceNotFound); } - ; return mutationEngine; } From 5544ef414749cfa126175938f3d1fa47b54ebede Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 11:54:03 +0530 Subject: [PATCH 07/12] Remove unused variable --- .../OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs b/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs index b5964a04d2..41771ad363 100644 --- a/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs +++ b/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs @@ -22,7 +22,6 @@ public class CLRtoJsonValueTypeUnitTests private const string SQLDBTYPE_RESOLUTION_ERROR = "failed to resolve to SqlDbType."; private const string SQLDBTYPE_UNEXPECTED_RESOLUTION_ERROR = "should have resolved to a SqlDbType."; private const string JSONDATATYPE_RESOLUTION_ERROR = "(when supported) should map to a system type and associated JsonDataType."; - private const string DBTYPE_RESOLUTION_ERROR = "(when supported) should map to a system type and associated DbType."; /// /// Validates that: From 5e3175bbf00f6937dcc00e5ea10ca05543b85cb3 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 13:20:32 +0530 Subject: [PATCH 08/12] Fix SqlTestHelper for Microsoft.Data.SqlClient 6.x SqlError constructor change SqlClient 6.x changed the internal SqlError 9-parameter constructor: the win32ErrorCode parameter is now Int32 (was UInt32 in 5.x), and there are now multiple 9-parameter overloads. Select the constructor by exact parameter types and pass (int)0 for win32ErrorCode so CreateSqlException works across SqlClient versions. --- src/Service.Tests/SqlTests/SqlTestHelper.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Service.Tests/SqlTests/SqlTestHelper.cs b/src/Service.Tests/SqlTests/SqlTestHelper.cs index cf65c9a9f5..32041c8fc8 100644 --- a/src/Service.Tests/SqlTests/SqlTestHelper.cs +++ b/src/Service.Tests/SqlTests/SqlTestHelper.cs @@ -552,15 +552,24 @@ public static SqlException CreateSqlException(int number, string message = "") // Get all the available non-public,non-static constructors for SqlError class. constructorsArray = typeof(SqlError).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance); - // At this point the ConstructorInfo[] for SqlError has 2 entries: One constructor with 8 parameters, - // and one with 9 parameters. We can choose either of them to create an object of SqlError type. - ConstructorInfo nineParamsConstructor = constructorsArray.FirstOrDefault(c => c.GetParameters().Length == 9); + // Microsoft.Data.SqlClient exposes multiple internal SqlError constructors (including more than + // one with nine parameters). Select the specific overload by matching its exact parameter types + // so we are resilient to constructor ordering and signature changes across SqlClient versions: + // (int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, + // string procedure, int lineNumber, int win32ErrorCode, Exception exception) + Type[] expectedParameterTypes = new[] + { + typeof(int), typeof(byte), typeof(byte), typeof(string), typeof(string), + typeof(string), typeof(int), typeof(int), typeof(Exception) + }; + ConstructorInfo sqlErrorConstructor = constructorsArray.FirstOrDefault(c => + c.GetParameters().Select(p => p.ParameterType).SequenceEqual(expectedParameterTypes)); // Create SqlError object. // For details on what the parameters stand for please refer: // https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlerror.number#examples - SqlError sqlError = (nineParamsConstructor - .Invoke(new object[] { number, (byte)0, (byte)0, "", "", "", (int)0, (uint)0, null }) as SqlError)!; + SqlError sqlError = (sqlErrorConstructor + .Invoke(new object[] { number, (byte)0, (byte)0, "", "", "", (int)0, (int)0, null }) as SqlError)!; errorList.Add(sqlError); // Create SqlException object From f840076e2ae930da125fb2ae5a2c8901de5783ac Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Thu, 18 Jun 2026 14:07:43 +0530 Subject: [PATCH 09/12] Treat empty ASPNETCORE_URLS as valid in ValidateAspNetCoreUrls Starting with .NET 10, setting an environment variable to an empty string preserves it as an empty value instead of deleting it (which previously surfaced here as null). This caused ValidateAspNetCoreUrls to treat an empty ASPNETCORE_URLS as invalid and exit with error, a regression from .NET 8 where an empty value was equivalent to unset. Explicitly treat an empty value as valid (Kestrel falls back to default URLs), preserving the prior behavior. Whitespace-only values remain invalid. --- src/Service/Program.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Service/Program.cs b/src/Service/Program.cs index e83dde30c7..7f315f0655 100644 --- a/src/Service/Program.cs +++ b/src/Service/Program.cs @@ -531,6 +531,15 @@ internal static bool ValidateAspNetCoreUrls() return true; // If the environment variable is missing, then it cannot be invalid. } + if (string.IsNullOrEmpty(urls)) + { + // An empty value is equivalent to the variable being unset: Kestrel falls back to its + // default URLs, so this is valid. Note that starting with .NET 10, setting an environment + // variable to an empty string preserves it as "" instead of deleting it (which previously + // surfaced here as null), so this case must be handled explicitly. + return true; + } + if (string.IsNullOrWhiteSpace(urls)) { return false; From ed820fb4f6ae39b5ec203829bce6febd36ef0393 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Fri, 19 Jun 2026 13:32:52 +0530 Subject: [PATCH 10/12] Revert unrelated changes to match main (PR review feedback) These three files were modified by an earlier merge in a way unrelated to the .NET 10 / SqlClient 6.x upgrade, reverting recent main formatting/cleanup: - CLRtoJsonValueTypeUnitTests.cs: restore the DBTYPE_RESOLUTION_ERROR constant that was inadvertently removed. - SqlUpdateQueryStructure.cs: restore main's formatting of the update-fields block. - MutationEngineFactory.cs: restore main's version. Restoring them to match main keeps this PR scoped to the upgrade and addresses reviewer feedback (constant removal and formatting). --- .../Factories/MutationEngineFactory.cs | 2 +- .../SqlUpdateQueryStructure.cs | 30 +++++++++---------- .../CLRtoJsonValueTypeUnitTests.cs | 1 + 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Core/Resolvers/Factories/MutationEngineFactory.cs b/src/Core/Resolvers/Factories/MutationEngineFactory.cs index 08a5fea2e3..9b4df9f8bf 100644 --- a/src/Core/Resolvers/Factories/MutationEngineFactory.cs +++ b/src/Core/Resolvers/Factories/MutationEngineFactory.cs @@ -107,7 +107,7 @@ public IMutationEngine GetMutationEngine(DatabaseType databaseType) $"{nameof(databaseType)}:{databaseType} could not be found within the config", HttpStatusCode.BadRequest, DataApiBuilderException.SubStatusCodes.DataSourceNotFound); - } + }; return mutationEngine; } diff --git a/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs b/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs index 2fffa19ef5..ecbbf3fc5c 100644 --- a/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs +++ b/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs @@ -122,26 +122,26 @@ public SqlUpdateStructure( Predicates.Add(CreatePredicateForParam(new KeyValuePair(pkBackingColumn, param.Value))); } else // Unpack the input argument type as columns to update - if (param.Key == UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME) + if (param.Key == UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME) + { + IDictionary updateFields = + GQLMutArgumentToDictParams(context, UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME, mutationParams); + + foreach (KeyValuePair field in updateFields) { - IDictionary updateFields = - GQLMutArgumentToDictParams(context, UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME, mutationParams); + string fieldBackingColumn = field.Key; + if (sqlMetadataProvider.TryGetBackingColumn(entityName, field.Key, out string? resolvedBackingColumn) + && !string.IsNullOrWhiteSpace(resolvedBackingColumn)) + { + fieldBackingColumn = resolvedBackingColumn; + } - foreach (KeyValuePair field in updateFields) + if (columns.Contains(fieldBackingColumn)) { - string fieldBackingColumn = field.Key; - if (sqlMetadataProvider.TryGetBackingColumn(entityName, field.Key, out string? resolvedBackingColumn) - && !string.IsNullOrWhiteSpace(resolvedBackingColumn)) - { - fieldBackingColumn = resolvedBackingColumn; - } - - if (columns.Contains(fieldBackingColumn)) - { - UpdateOperations.Add(CreatePredicateForParam(new KeyValuePair(key: fieldBackingColumn, field.Value))); - } + UpdateOperations.Add(CreatePredicateForParam(new KeyValuePair(key: fieldBackingColumn, field.Value))); } } + } } if (UpdateOperations.Count == 0) diff --git a/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs b/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs index 41771ad363..b5964a04d2 100644 --- a/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs +++ b/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs @@ -22,6 +22,7 @@ public class CLRtoJsonValueTypeUnitTests private const string SQLDBTYPE_RESOLUTION_ERROR = "failed to resolve to SqlDbType."; private const string SQLDBTYPE_UNEXPECTED_RESOLUTION_ERROR = "should have resolved to a SqlDbType."; private const string JSONDATATYPE_RESOLUTION_ERROR = "(when supported) should map to a system type and associated JsonDataType."; + private const string DBTYPE_RESOLUTION_ERROR = "(when supported) should map to a system type and associated DbType."; /// /// Validates that: From 3735ff46167db8562c3908f427427deab7adee50 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Fri, 19 Jun 2026 14:05:52 +0530 Subject: [PATCH 11/12] Fix .NET 10 formatter whitespace/style on Core mutation files --- .../Factories/MutationEngineFactory.cs | 2 +- .../SqlUpdateQueryStructure.cs | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Core/Resolvers/Factories/MutationEngineFactory.cs b/src/Core/Resolvers/Factories/MutationEngineFactory.cs index 9b4df9f8bf..08a5fea2e3 100644 --- a/src/Core/Resolvers/Factories/MutationEngineFactory.cs +++ b/src/Core/Resolvers/Factories/MutationEngineFactory.cs @@ -107,7 +107,7 @@ public IMutationEngine GetMutationEngine(DatabaseType databaseType) $"{nameof(databaseType)}:{databaseType} could not be found within the config", HttpStatusCode.BadRequest, DataApiBuilderException.SubStatusCodes.DataSourceNotFound); - }; + } return mutationEngine; } diff --git a/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs b/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs index ecbbf3fc5c..2fffa19ef5 100644 --- a/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs +++ b/src/Core/Resolvers/Sql Query Structures/SqlUpdateQueryStructure.cs @@ -122,26 +122,26 @@ public SqlUpdateStructure( Predicates.Add(CreatePredicateForParam(new KeyValuePair(pkBackingColumn, param.Value))); } else // Unpack the input argument type as columns to update - if (param.Key == UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME) - { - IDictionary updateFields = - GQLMutArgumentToDictParams(context, UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME, mutationParams); - - foreach (KeyValuePair field in updateFields) + if (param.Key == UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME) { - string fieldBackingColumn = field.Key; - if (sqlMetadataProvider.TryGetBackingColumn(entityName, field.Key, out string? resolvedBackingColumn) - && !string.IsNullOrWhiteSpace(resolvedBackingColumn)) - { - fieldBackingColumn = resolvedBackingColumn; - } + IDictionary updateFields = + GQLMutArgumentToDictParams(context, UpdateAndPatchMutationBuilder.INPUT_ARGUMENT_NAME, mutationParams); - if (columns.Contains(fieldBackingColumn)) + foreach (KeyValuePair field in updateFields) { - UpdateOperations.Add(CreatePredicateForParam(new KeyValuePair(key: fieldBackingColumn, field.Value))); + string fieldBackingColumn = field.Key; + if (sqlMetadataProvider.TryGetBackingColumn(entityName, field.Key, out string? resolvedBackingColumn) + && !string.IsNullOrWhiteSpace(resolvedBackingColumn)) + { + fieldBackingColumn = resolvedBackingColumn; + } + + if (columns.Contains(fieldBackingColumn)) + { + UpdateOperations.Add(CreatePredicateForParam(new KeyValuePair(key: fieldBackingColumn, field.Value))); + } } } - } } if (UpdateOperations.Count == 0) From a808e13252e0201566e8e6557a1b0564ecc56397 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Fri, 19 Jun 2026 14:11:39 +0530 Subject: [PATCH 12/12] remove unused variable due to strict check by .Net 10 --- .../OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs b/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs index b5964a04d2..41771ad363 100644 --- a/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs +++ b/src/Service.Tests/OpenApiDocumentor/CLRtoJsonValueTypeUnitTests.cs @@ -22,7 +22,6 @@ public class CLRtoJsonValueTypeUnitTests private const string SQLDBTYPE_RESOLUTION_ERROR = "failed to resolve to SqlDbType."; private const string SQLDBTYPE_UNEXPECTED_RESOLUTION_ERROR = "should have resolved to a SqlDbType."; private const string JSONDATATYPE_RESOLUTION_ERROR = "(when supported) should map to a system type and associated JsonDataType."; - private const string DBTYPE_RESOLUTION_ERROR = "(when supported) should map to a system type and associated DbType."; /// /// Validates that: