Skip to content

Upgrade to .NET 10 and Microsoft.Data.SqlClient 6.x - #3656

Merged
souvikghosh04 merged 19 commits into
mainfrom
Usr/sogh/upgrade-net10-sqlclient6
Jun 24, 2026
Merged

Upgrade to .NET 10 and Microsoft.Data.SqlClient 6.x#3656
souvikghosh04 merged 19 commits into
mainfrom
Usr/sogh/upgrade-net10-sqlclient6

Conversation

@souvikghosh04

@souvikghosh04 souvikghosh04 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Joint runtime + driver bump to unblock two new SQL datatypes — JSON (#2768) and Vector (#2767).

This is a no-behavior-change prerequisite PR. It does not implement JSON or Vector itself; it raises the runtime and driver floor so the companion feature PRs can compile and run.

WHY BOTH BUMPS ARE REQUIRED TOGETHER

Two separate datatype features both depend on this baseline:

  1. JSON ([Enh]: Support JSON data type for MSSQL #2768) — needs the .NET 10 BCL enum value.
    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<SqlDbType>("json", ignoreCase: true, out _)
    

    in TypeHelper.GetSystemTypeFromSqlDbType returns false regardless of which SqlClient version is installed. The companion feature PR for [Enh]: Support JSON data type for MSSQL #2768 plans to add a single dictionary entry

    [SqlDbType.Json] = typeof(string)
    

    which simply will not compile on net8.0.

  2. Vector ([Enh]: Support Vector data type in MSSQL #2767) — needs Microsoft.Data.SqlClient 6.1.x.
    The SqlVector type (extending System.Data.SqlTypes) was introduced in Microsoft.Data.SqlClient 6.1.0. DAB's current driver (5.2.3) has no such type, so vector columns/parameters cannot be discovered or round-tripped. The Vector foundation work (Foundation for adding support for Vector Data Type #3654, child of [Enh]: Support Vector data type in MSSQL #2767) requires the driver to be on the 6.1.x line. This PR pins 6.1.5.

Because JSON needs .NET 10 and Vector needs SqlClient 6.1.x, and both feature PRs build on the same baseline, both upgrades must 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.

WHY SqlClient 6.1.x AND NOT 7.x

6.1.5 already delivers everything these features need: SqlVector (6.1) for Vector, and JSON support paired with the .NET 10 BCL SqlDbType.Json enum. 7.0 introduces a breaking change — the Azure auth stack (Azure.Core, Azure.Identity, Microsoft.Identity.Client) is extracted out of the core package into a separate Microsoft.Data.SqlClient.Extensions.Azure package — which would affect DAB's managed-identity / Entra ID auth paths and is out of scope for a no-behavior-change PR. Issue #3422's intent (get off the 2-versions-behind 5.2.3 line) is satisfied by 6.1.x. A move to 7.x is deferred to a dedicated follow-up.

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.1.5
  • 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.2.License.txt
    (SqlClient 6.1.5 depends on Microsoft.Data.SqlClient.SNI.runtime 6.0.2.)
  • 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
dotnet build -c Debug : 0 warnings, 0 errors

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.2.License.txt from upstream for the SNI 6.0.2 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.
  5. File follow-up issue to evaluate Microsoft.Data.SqlClient 7.x (adds Microsoft.Data.SqlClient.Extensions.Azure, re-validate Entra ID / managed-identity auth).

Why make this change?

What is this change?

How was this tested?

  • Integration Tests (multi-engine CI matrix is the merge gate)
  • Unit Tests

Sample Request(s)

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<SqlDbType>("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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades Data API Builder’s build/runtime baseline to .NET 10 (SDK pin + project TFMs) and bumps Microsoft.Data.SqlClient to 6.x as a prerequisite for upcoming SQL JSON / vector datatype support that depends on SqlDbType.Json being present in the BCL.

Changes:

  • Pin SDK to .NET 10.0.301 and retarget all src/** projects from net8.0 to net10.0.
  • Update central package versions (notably Microsoft.Data.SqlClient 6.0.2 and required Microsoft.Extensions.* 10.0.0) and remove now-redundant Service package refs.
  • Update pipelines/scripts/container images to build with .NET 10 and adjust ancillary release/notice assets (including SNI license file rename).

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
global.json Pins repo SDK to 10.0.301.
src/Service/Azure.DataApiBuilder.Service.csproj Retarget to net10.0, add ASPDEPR008 suppression, remove redundant config package refs.
src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj Retarget tests to net10.0, add ASPDEPR008 suppression.
src/Core/Azure.DataApiBuilder.Core.csproj Retarget core library to net10.0.
src/Config/Azure.DataApiBuilder.Config.csproj Retarget config library to net10.0.
src/Auth/Azure.DataApiBuilder.Auth.csproj Retarget auth library to net10.0.
src/Cli/Cli.csproj Retarget CLI to net10.0.
src/Cli.Tests/Cli.Tests.csproj Retarget CLI tests to net10.0.
src/Product/Azure.DataApiBuilder.Product.csproj Retarget product project to net10.0.
src/Service.GraphQLBuilder/Azure.DataApiBuilder.Service.GraphQLBuilder.csproj Retarget GraphQL builder to net10.0.
src/Azure.DataApiBuilder.Mcp/Azure.DataApiBuilder.Mcp.csproj Retarget MCP project to net10.0.
src/Aspire.AppHost/Aspire.AppHost.csproj Retarget Aspire AppHost to net10.0.
src/Aspire.AppHost/AppHost.cs Update AppHost args from net8.0 to net10.0.
src/Directory.Packages.props Bump SqlClient + required Microsoft.Extensions.* packages to 10/6.x.
Dockerfile Move SDK/runtime base images to .NET 10 Azure Linux tags.
scripts/publish.ps1 Update publish framework strings to net10.0.
scripts/create-manifest-file.ps1 Update manifest framework keys to net10.0_*.
scripts/notice-generation.ps1 Update SNI license file path for notice generation.
external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt Renamed SNI license file for SqlClient 6.x (currently includes a TODO marker).
.pipelines/templates/static-tools.yml UseDotNet version updated to 10.0.x.
.pipelines/templates/mssql-test-steps.yml UseDotNet version updated to 10.0.x.
.pipelines/templates/build-pipelines.yml UseDotNet version updated to 10.0.x.
.pipelines/pg-pipelines.yml UseDotNet version updated to 10.0.x.
.pipelines/mysql-pipelines.yml UseDotNet version updated to 10.0.x.
.pipelines/mssql-pipelines.yml UseDotNet version updated to 10.0.x.
.pipelines/dwsql-pipelines.yml UseDotNet version updated to 10.0.x (linux + windows jobs).
.pipelines/cosmos-pipelines.yml UseDotNet version updated to 10.0.x.
Comments suppressed due to low confidence (1)

external_licenses/Microsoft.Data.SqlClient.SNI.6.0.0.License.txt:5

  • This license file still contains a TODO marker stating the body is for SNI 5.2.0, not the updated 6.0.0 version. Shipping with an intentionally stale license text (and an in-file TODO note) is a compliance risk; the file should be refreshed from the upstream SNI 6.0.0 license source before merge.

Comment thread .pipelines/templates/static-tools.yml Outdated
Comment thread .pipelines/templates/mssql-test-steps.yml Outdated
Comment thread .pipelines/templates/build-pipelines.yml Outdated
Comment thread .pipelines/pg-pipelines.yml Outdated
Comment thread .pipelines/mysql-pipelines.yml Outdated
Comment thread .pipelines/dwsql-pipelines.yml Outdated
Comment thread .pipelines/cosmos-pipelines.yml Outdated
Comment thread src/Service/Azure.DataApiBuilder.Service.csproj Outdated
Comment thread src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj Outdated
Comment thread scripts/create-manifest-file.ps1 Outdated
RubenCerna2079 and others added 4 commits June 17, 2026 17:29
- 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
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.
@souvikghosh04
souvikghosh04 marked this pull request as draft June 18, 2026 06:32
@souvikghosh04 souvikghosh04 moved this from In Progress to Review In Progress in Data API builder Jun 19, 2026
@aaronburtle

Copy link
Copy Markdown
Contributor

.devcontainer\devcontainer.json

"name": ".NET 8",
"image": "mcr.microsoft.com/dotnet/sdk:8.0",

"dotnetRuntimeVersions": "8.0",
"aspNetCoreRuntimeVersions": "8.0",
"additionalVersions": "8.0"

Is still pinned to .NET 8, is that intended?

@aaronburtle

Copy link
Copy Markdown
Contributor

.github\copilot-instructions.md

This still documents .NET8

@aaronburtle aaronburtle left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just noticed a couple places where we still have .NET8 remaining

@souvikghosh04
souvikghosh04 enabled auto-merge (squash) June 24, 2026 06:11
@souvikghosh04
souvikghosh04 merged commit 84c58b7 into main Jun 24, 2026
12 checks passed
@github-project-automation github-project-automation Bot moved this from Review In Progress to Done in Data API builder Jun 24, 2026
@souvikghosh04
souvikghosh04 deleted the Usr/sogh/upgrade-net10-sqlclient6 branch June 24, 2026 17:30
souvikghosh04 added a commit that referenced this pull request Jul 14, 2026
…ngine) (#3691)

## What this PR does

Adds support for the SQL Server 2025 `JSON` column type by treating it
exactly like a normal text (`string`) column. Reading, writing,
filtering, and sorting all reuse the paths DAB already has for strings —
no new type, no special handling.

## The change

Two small edits to the engine:

1. **Map the type** — tell DAB that a `JSON` column is a `string`.
2. **Map the errors** — when SQL Server rejects invalid JSON, return
**HTTP 400 (Bad Request)** instead of a generic 500.

Both are covered by new unit tests.

This PR is intentionally scoped to just the engine change. The database
test table and end-to-end (REST/GraphQL) tests are **not** included here
because they need a real SQL Server 2025 database — and our CI currently
runs on LocalDB, which doesn't understand the `JSON` type yet. Those
tests come in the next phase.

## Delivery plan

| Phase | What | Status |
|------|------|--------|
| 1 | Upgrade to .NET 10 + SqlClient 6.x (prerequisite) | ✅ Merged
(#3656) |
| 2 | JSON type + error mapping | This PR |
| 3 | Test table + full REST/GraphQL/MCP tests | Next |
| 4 | Error/filter edge cases + regression | After |

## Notes
- No changes to PostgreSQL, MySQL, DwSql, or CosmosDB.
- Related issue: #2768.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
souvikghosh04 added a commit that referenced this pull request Jul 28, 2026
## What this PR does

Adds the database test fixture and REST integration tests for SQL Server
2025 `JSON` columns. It builds on Phase 2 (which taught the engine to
treat `JSON` as a normal `string`) and proves the behavior end-to-end
through the REST API.

This follows the exact pattern of the recently merged **vector data
type** feature (#3677), and is unblocked by CI now running SQL Server
2025 (#3697).

## What's included

- **Test table** — a `profiles` table with an `id` and a `metadata json`
column, plus 5 seed rows covering a simple object, an array, a deeply
nested object, unicode + emoji, and `NULL`.
- **Entity** — a `Profile` entity (REST + GraphQL enabled) in the MsSql
test config and config generator.
- **REST tests** — `MsSqlRestJsonTypesTests`: read (list, by id, null,
array, nested, unicode), insert, update (PUT/PATCH), clear-to-null, and
delete.

Because DAB treats `JSON` as a string, the tests parse `metadata` and
compare it **semantically**, so they're robust to any whitespace /
key-order normalization the engine applies.

## No gating needed

Unlike the earlier plan, the table is created **unconditionally** (no
server-version guard) — CI runs SQL Server 2025 and the schema already
uses the 2025-only `vector` type the same way.

## Delivery plan

| Phase | What | Status |
|------|------|--------|
| 1 | .NET 10 + SqlClient 6.x (prerequisite) | ✅ Merged (#3697/#3656) |
| 2 | JSON type + error mapping (engine) | ✅ Merged (#3691) |
| **3** | **Test fixture + REST CRUD tests (this PR)** | 🚧 In review |
| 3b | GraphQL / OpenAPI / MCP schema-discovery tests | Next |
| 4 | Error/filter edge cases + regression | After |

## Notes
- Requires SQL Server 2025 / Azure SQL (native `json` type).
- No changes to PostgreSQL, MySQL, DwSql, or CosmosDB.
- Related issue: #2768.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
souvikghosh04 added a commit that referenced this pull request Jul 30, 2026
…QL tests (#3738)

## Why

Part of MSSQL native `JSON` support (#2768). Started as Phase 3b
**schema-discovery tests**, but review (thanks @aaronburtle) surfaced a
real product inconsistency that this PR now also fixes.

**The problem:** #2768 requires a `JSON` column to be treated as a
normal `string` for **input and output**. But the MSSQL read path (`FOR
JSON PATH`) was *inlining* a native `json` column as a nested JSON
**object**. Consequences:
- REST returned `"metadata": {"role":"admin"}` (object) instead of
`"metadata": "{\"role\":\"admin\"}"` (string).
- A GraphQL read of the `String`-typed field threw a `GraphQLMapping`
error — the `String` leaf resolver calls `JsonElement.GetString()`,
which fails on an object. So schema introspection could pass while
`profile_by_pk(id:1){ metadata }` failed at runtime.
- OpenAPI/GraphQL advertised `string`, contradicting the object runtime
— generated clients would mis-model the field.

## What

**Engine fix** (`MsSqlQueryBuilder`): the read path now casts a native
`json` column (`SqlDbType.Json`) to `NVARCHAR(MAX)` in `WrappedColumns`,
so `FOR JSON PATH` emits it as an escaped JSON **string** rather than
inlining it as an object. This is the single choke point for REST
**and** GraphQL reads. Regular `nvarchar` columns are untouched.
Mutations already return `json` as a string via the tabular `OUTPUT`
clause, so no change was needed there.

**Tests:**

| Layer | Test | Asserts |
|------|------|---------|
| OpenAPI | `JsonTypeSchemaTests` | `metadata` is `type: string` with no
`format` in the **response** and both **request-body** schemas
(`Profile_NoAutoPK` for POST, `Profile_NoPK` for PUT/PATCH) |
| GraphQL introspection | `MsSqlGraphQLJsonSchemaTests` |
`Profile.metadata` is the built-in `String` scalar (no custom JSON
scalar) |
| GraphQL read (new) | `MsSqlGraphQLJsonSchemaTests` |
`profile_by_pk(id:1){ metadata }` returns the payload as a JSON
**string** — guards against introspection passing while a real read
throws |
| REST | `MsSqlRestJsonTypesTests` (updated) | flipped back to the
string contract: `metadata` is returned as a JSON **string**
(`ParseMetadata`/`GetJsonTypeList` assert `JsonValueKind.String`) |

> Note: DAB's OpenAPI documentor does not emit `Nullable` on the
property schema for **any** column type, so the schema tests assert
`type: string` + no `format` (not nullability).

## Intentionally omitted

- **MCP `describe_entities` (T010)**: it projects only the config field
`name`/`description`, not DB column data types, so there is no
JSON-specific behavior to assert.

## Notes

- **This PR now includes a product (engine) change**, not tests only.
- Requires SQL Server 2025 / Azure SQL (native `json`); CI already runs
SQL 2025.
- Cannot be run locally (no SQL 2025 here) — relying on CI.

## Delivery plan

| Phase | What | Status |
|-------|------|--------|
| 1 | .NET 10 + SqlClient 6.x | ✅ Merged (#3697/#3656) |
| 2 | JSON type + error mapping (engine) | ✅ Merged (#3691) |
| 3 | Test fixture + REST CRUD tests | ✅ Merged (#3720) |
| **3b** | **json-as-string read fix + OpenAPI/GraphQL discovery & read
tests (this PR)** | 🚧 |
| 4 | Error/filter edge cases + regression + polish | Next |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Upgrade .Net and SQLClient to support JSON and Vector data types

5 participants