diff --git a/Directory.Packages.props b/Directory.Packages.props index 5d132254a9d..a013d0f7578 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -38,7 +38,7 @@ - + @@ -51,7 +51,7 @@ - + diff --git a/NuGet.config b/NuGet.config index 212a973207a..6d9be61db0c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -26,4 +26,8 @@ + + + + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index e12ddae3450..cfc3516efbd 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,24 +6,24 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26361.102 - 10.0.0-beta.26361.102 - 10.0.0-beta.26361.102 - 10.0.10 - 10.0.10 - 10.0.10 - 10.0.10 - 10.0.10 - 10.0.10 - 10.0.10 - 10.0.10-servicing.26361.102 - 10.0.10 - 10.0.10 - 10.0.10-servicing.26361.102 - 10.0.10 - 10.0.10 - 10.0.10 - 10.0.10 + 10.0.0-beta.26376.103 + 10.0.0-beta.26376.103 + 10.0.0-beta.26376.103 + 10.0.12 + 10.0.12 + 10.0.12 + 10.0.12 + 10.0.12 + 10.0.12 + 10.0.12 + 10.0.12-servicing.26376.103 + 10.0.12 + 10.0.12 + 10.0.12-servicing.26376.103 + 10.0.12 + 10.0.12 + 10.0.12 + 10.0.12 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9f3c9af3864..60d5215d02d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,80 +1,80 @@ - + - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d - + https://github.com/dotnet/dotnet - b63fd14d0c0dc26a52814d3f8debb67ba806f1f0 + e0c9b3f934e7b97b360f4ce3692ab45b9634ae1d diff --git a/eng/Versions.props b/eng/Versions.props index 0aa194847ae..796c1dd6f65 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,7 +1,7 @@ - 10.0.10 + 10.0.12 servicing False @@ -30,11 +30,11 @@ 1.1.3-beta1.24352.1 1.21.0 1.3.2 - 1.12.0 + 1.17.0 2.1.12 2.1.11 2.1.11 2.1.11 - 2.3.5 + 2.3.6 diff --git a/eng/common/build.ps1 b/eng/common/build.ps1 index 8cfee107e7a..18397a60eb8 100644 --- a/eng/common/build.ps1 +++ b/eng/common/build.ps1 @@ -6,6 +6,7 @@ Param( [string][Alias('v')]$verbosity = "minimal", [string] $msbuildEngine = $null, [bool] $warnAsError = $true, + [string] $warnNotAsError = '', [bool] $nodeReuse = $true, [switch] $buildCheck = $false, [switch][Alias('r')]$restore, @@ -70,6 +71,7 @@ function Print-Usage() { Write-Host " -excludeCIBinarylog Don't output binary log (short: -nobl)" Write-Host " -prepareMachine Prepare machine for CI run, clean up processes after build" Write-Host " -warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" + Write-Host " -warnNotAsError Sets a semi-colon delimited list of warning codes that should not be treated as errors" Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." Write-Host " -excludePrereleaseVS Set to exclude build engines in prerelease versions of Visual Studio" Write-Host " -nativeToolsOnMachine Sets the native tools on machine environment variable (indicating that the script should use native tools on machine)" diff --git a/eng/common/build.sh b/eng/common/build.sh index 9767bb411a4..c8bea7cbc2d 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -42,6 +42,7 @@ usage() echo " --prepareMachine Prepare machine for CI run, clean up processes after build" echo " --nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')" echo " --warnAsError Sets warnaserror msbuild parameter ('true' or 'false')" + echo " --warnNotAsError Sets a semi-colon delimited list of warning codes that should not be treated as errors" echo " --buildCheck Sets /check msbuild parameter" echo " --fromVMR Set when building from within the VMR" echo "" @@ -78,6 +79,7 @@ ci=false clean=false warn_as_error=true +warn_not_as_error='' node_reuse=true build_check=false binary_log=false @@ -176,6 +178,10 @@ while [[ $# > 0 ]]; do warn_as_error=$2 shift ;; + -warnnotaserror) + warn_not_as_error=$2 + shift + ;; -nodereuse) node_reuse=$2 shift diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index eefed3b667a..12d7e55a94b 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -8,6 +8,12 @@ parameters: CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + # Service connection for WIF-based Entra authentication to ceapex feeds (replaces CeapexPat). + # When set, dnceng/internal builds acquire a federated Entra token instead of using a PAT. + # All other projects (e.g. DevDiv, public), where this dnceng-scoped service connection does not + # exist, and any pipeline that sets this to '' fall back to PAT-based auth via the CeapexPat parameter. + CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' + SourcesDirectory: $(System.DefaultWorkingDirectory) CreatePr: true AutoCompletePr: false @@ -73,6 +79,15 @@ jobs: displayName: Generate LocProject.json condition: ${{ parameters.condition }} + # Acquire an Entra token for ceapex feed access via WIF (dnceng/internal only). + # All other projects use PAT-based auth, since the ceapex service connection is scoped to dnceng/internal. + - ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + - template: /eng/common/templates/steps/get-federated-access-token.yml + parameters: + federatedServiceConnection: ${{ parameters.CeapexServiceConnection }} + outputVariableName: 'CeapexEntraToken' + condition: ${{ parameters.condition }} + - task: OneLocBuild@2 displayName: OneLocBuild env: @@ -88,7 +103,10 @@ jobs: isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} + ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + patVariable: $(CeapexEntraToken) + ${{ if or(eq(parameters.CeapexServiceConnection, ''), ne(variables['System.TeamProject'], 'internal')) }}: + patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} gitHubPatVariable: "${{ parameters.GithubPat }}" diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index 06f2eed0323..53af522d6d4 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -122,9 +122,6 @@ jobs: # Populate internal runtime variables. - template: /eng/common/templates/steps/enable-internal-sources.yml - ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: - parameters: - legacyCredential: $(dn-bot-dnceng-artifact-feeds-rw) - template: /eng/common/templates/steps/enable-internal-runtimes.yml diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index 905a6315e2d..135fc9a5051 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -352,8 +352,6 @@ stages: # Populate internal runtime variables. - template: /eng/common/templates/steps/enable-internal-sources.yml - parameters: - legacyCredential: $(dn-bot-dnceng-artifact-feeds-rw) - template: /eng/common/templates/steps/enable-internal-runtimes.yml diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 977a2d4b103..bde220ad85b 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -34,6 +34,9 @@ # Configures warning treatment in msbuild. [bool]$warnAsError = if (Test-Path variable:warnAsError) { $warnAsError } else { $true } +# Specifies semi-colon delimited list of warning codes that should not be treated as errors. +[string]$warnNotAsError = if (Test-Path variable:warnNotAsError) { $warnNotAsError } else { '' } + # Specifies which msbuild engine to use for build: 'vs', 'dotnet' or unspecified (determined based on presence of tools.vs in global.json). [string]$msbuildEngine = if (Test-Path variable:msbuildEngine) { $msbuildEngine } else { $null } @@ -732,7 +735,7 @@ function InitializeToolset() { '' | Set-Content $proj - MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile + MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile /p:RestoreIgnoreFailedSources=true $path = Get-Content $toolsetLocationFile -Encoding UTF8 -TotalCount 1 if (!(Test-Path $path)) { @@ -836,6 +839,11 @@ function MSBuild-Core() { $cmdArgs += ' /p:TreatWarningsAsErrors=false' } + if ($warnAsError -and $warnNotAsError) { + $escapedWarnNotAsError = $warnNotAsError -replace ';', '%3B' + $cmdArgs += " /warnnotaserror:$warnNotAsError /p:AdditionalWarningsNotAsErrors=$escapedWarnNotAsError" + } + foreach ($arg in $args) { if ($null -ne $arg -and $arg.Trim() -ne "") { if ($arg.EndsWith('\')) { diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 1b296f646c2..df76f062a76 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -52,6 +52,9 @@ fi # Configures warning treatment in msbuild. warn_as_error=${warn_as_error:-true} +# Specifies semi-colon delimited list of warning codes that should not be treated as errors. +warn_not_as_error=${warn_not_as_error:-''} + # True to attempt using .NET Core already that meets requirements specified in global.json # installed on the machine instead of downloading one. use_installed_dotnet_cli=${use_installed_dotnet_cli:-true} @@ -430,7 +433,7 @@ function InitializeToolset { fi echo '' > "$proj" - MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" + MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" /p:RestoreIgnoreFailedSources=true local toolset_build_proj=`cat "$toolset_location_file"` @@ -532,7 +535,12 @@ function MSBuild-Core { mt_switch="-mt" fi - RunBuildTool "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch $mt_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" + local warnnotaserror_switch="" + if [[ -n "$warn_not_as_error" && "$warn_as_error" == true ]]; then + warnnotaserror_switch="/warnnotaserror:$warn_not_as_error /p:AdditionalWarningsNotAsErrors=${warn_not_as_error//;/%3B}" + fi + + RunBuildTool "$_InitializeBuildToolCommand" /m /nologo /clp:Summary /v:$verbosity /nr:$node_reuse $warnaserror_switch $mt_switch $warnnotaserror_switch /p:TreatWarningsAsErrors=$warn_as_error /p:ContinuousIntegrationBuild=$ci "$@" } function GetDarc { diff --git a/global.json b/global.json index 110c07bbe68..96fbf113502 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.109", + "version": "10.0.110", "allowPrerelease": true, "rollForward": "latestMajor", "paths": [ @@ -10,7 +10,7 @@ "errorMessage": "The required .NET SDK wasn't found. Please run ./restore.sh or .\\restore.cmd to install it." }, "tools": { - "dotnet": "10.0.109", + "dotnet": "10.0.110", "runtimes": { "dotnet": [ "$(MicrosoftNETCorePlatformsVersion)" @@ -18,7 +18,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26361.102", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26361.102" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26376.103", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26376.103" } } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index f260058111b..b8032897e13 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -792,8 +792,22 @@ void GenerateColumnInfo(SqlServerOpenJsonExpression.ColumnInfo columnInfo) { Sql .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(columnInfo.Name)) - .Append(" ") - .Append(columnInfo.TypeMapping.StoreType); + .Append(" "); + + // OPENJSON() WITH clause AS JSON option requires nvarchar(max) on platforms that don't support the json data + // type in OPENJSON (i.e. Azure SQL). SQL Server 2025 (17.x) added native support for json in OPENJSON WITH. + // See: https://learn.microsoft.com/sql/t-sql/data-types/json-data-type#limitations + if (columnInfo.AsJson + && columnInfo.TypeMapping.StoreType == "json" + && (_sqlServerSingletonOptions.EngineType != SqlServerEngineType.SqlServer + || _sqlServerSingletonOptions.SqlServerCompatibilityLevel < 170)) + { + Sql.Append("nvarchar(max)"); + } + else + { + Sql.Append(columnInfo.TypeMapping.StoreType); + } if (columnInfo.Path is not null) { diff --git a/test/Directory.Packages.props b/test/Directory.Packages.props index 75a7da0fc2c..3ee51cb8e6d 100644 --- a/test/Directory.Packages.props +++ b/test/Directory.Packages.props @@ -10,8 +10,8 @@ - - + + diff --git a/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryRelationalTestBase.cs index f99990292a3..e322b963948 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryRelationalTestBase.cs @@ -691,6 +691,99 @@ public class JsonNestedType #endregion HasJsonPropertyName + #region 38615 + + [ConditionalFact] + public virtual async Task SelectMany_over_primitive_collection_nested_in_complex_collection_inside_json_column() + { + var contextFactory = await InitializeAsync( + onConfiguring: b => b.ConfigureWarnings(ConfigureWarnings), + onModelCreating: m => m.Entity(b => + { + b.ToTable("Cars"); + b.HasKey(e => e.CarId); + b.Property(e => e.Vin).IsUnicode(false).HasMaxLength(32); + b.Property(e => e.DealerId).IsUnicode(false).HasMaxLength(32); + b.HasIndex(e => new { e.Vin, e.DealerId }).IsUnique(); + + b.ComplexProperty(e => e.CarConfiguration, pp => + { + pp.ToJson("CarConfiguration"); + if (JsonColumnType != null) + { + pp.HasColumnType(JsonColumnType); + } + + pp.Property(p => p.CurrentTrim).HasJsonPropertyName("currentTrim"); + + pp.ComplexCollection(p => p.OptionPackages, op => + { + op.HasJsonPropertyName("optionPackages"); + op.Property(o => o.PackageId).HasJsonPropertyName("packageId"); + op.PrimitiveCollection(o => o.PartNumbers) + .ElementType(e => e.IsUnicode(false).HasMaxLength(32)) + .HasJsonPropertyName("partNumbers"); + }); + }); + }), + seed: context => + { + context.Set().Add( + new Context38615.Car + { + Vin = "1FA6P8TH8J5123456", + DealerId = "DEALER-001", + CarConfiguration = new Context38615.CarConfiguration + { + CurrentTrim = "GT-Line", + OptionPackages = + [ + new Context38615.OptionPackage { PackageId = "PKG-SPORT", PartNumbers = ["SP-100", "SP-101"] }, + new Context38615.OptionPackage { PackageId = "PKG-TOW", PartNumbers = ["TW-200"] } + ] + } + }); + + return context.SaveChangesAsync(); + }); + + await using var context = contextFactory.CreateContext(); + + var partNumbers = await context.Set() + .Where(c => c.Vin == "1FA6P8TH8J5123456" && c.DealerId == "DEALER-001") + .SelectMany(c => c.CarConfiguration.OptionPackages) + .Where(op => op.PackageId == "PKG-SPORT") + .SelectMany(op => op.PartNumbers) + .ToListAsync(); + + Assert.Equal(["SP-100", "SP-101"], partNumbers.Order().ToList()); + } + + protected class Context38615(DbContextOptions options) : DbContext(options) + { + public class Car + { + public int CarId { get; set; } + public string Vin { get; set; } + public string DealerId { get; set; } + public CarConfiguration CarConfiguration { get; set; } + } + + public class CarConfiguration + { + public string CurrentTrim { get; set; } + public List OptionPackages { get; set; } + } + + public class OptionPackage + { + public string PackageId { get; set; } + public ICollection PartNumbers { get; set; } + } + } + + #endregion 38615 + protected TestSqlLoggerFactory TestSqlLoggerFactory => (TestSqlLoggerFactory)ListLoggerFactory; diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/AdHocJsonQuerySqlServerTestBase.cs b/test/EFCore.SqlServer.FunctionalTests/Query/AdHocJsonQuerySqlServerTestBase.cs index 9d0c333adf0..42162170e50 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/AdHocJsonQuerySqlServerTestBase.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/AdHocJsonQuerySqlServerTestBase.cs @@ -680,4 +680,60 @@ FROM [MyEntity] AS [m] INNER JOIN [OtherTable] AS [o] ON [m].[Id] = [o].[Id] """); } + + public override async Task SelectMany_over_primitive_collection_nested_in_complex_collection_inside_json_column() + { + await base.SelectMany_over_primitive_collection_nested_in_complex_collection_inside_json_column(); + + switch (JsonColumnType) + { + case "json": + if (Microsoft.EntityFrameworkCore.TestUtilities.TestEnvironment.IsAzureSql) + { + AssertSql( + """ +SELECT [p].[value] +FROM [Cars] AS [c] +CROSS APPLY OPENJSON([c].[CarConfiguration], '$.optionPackages') WITH ( + [packageId] nvarchar(max) '$.packageId', + [partNumbers] nvarchar(max) '$.partNumbers' AS JSON +) AS [o] +CROSS APPLY OPENJSON([o].[partNumbers]) WITH ([value] varchar(32) '$') AS [p] +WHERE [c].[Vin] = '1FA6P8TH8J5123456' AND [c].[DealerId] = 'DEALER-001' AND [o].[packageId] = N'PKG-SPORT' +"""); + } + else + { + AssertSql( + """ +SELECT [p].[value] +FROM [Cars] AS [c] +CROSS APPLY OPENJSON([c].[CarConfiguration], '$.optionPackages') WITH ( + [packageId] nvarchar(max) '$.packageId', + [partNumbers] json '$.partNumbers' AS JSON +) AS [o] +CROSS APPLY OPENJSON([o].[partNumbers]) WITH ([value] varchar(32) '$') AS [p] +WHERE [c].[Vin] = '1FA6P8TH8J5123456' AND [c].[DealerId] = 'DEALER-001' AND [o].[packageId] = N'PKG-SPORT' +"""); + } + + break; + case "nvarchar(max)": + AssertSql( + """ +SELECT [p].[value] +FROM [Cars] AS [c] +CROSS APPLY OPENJSON([c].[CarConfiguration], '$.optionPackages') WITH ( + [packageId] nvarchar(max) '$.packageId', + [partNumbers] nvarchar(max) '$.partNumbers' AS JSON +) AS [o] +CROSS APPLY OPENJSON([o].[partNumbers]) WITH ([value] varchar(32) '$') AS [p] +WHERE [c].[Vin] = '1FA6P8TH8J5123456' AND [c].[DealerId] = 'DEALER-001' AND [o].[packageId] = N'PKG-SPORT' +"""); + break; + + default: + throw new UnreachableException(); + } + } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/AdHocJsonQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/AdHocJsonQuerySqliteTest.cs index 5aa4bb84dd1..f0ed3e138f3 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/AdHocJsonQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/AdHocJsonQuerySqliteTest.cs @@ -319,4 +319,8 @@ INSERT INTO Entities (Id, Scenario, OptionalReference, RequiredReference, Collec ]') """); } + + public override Task SelectMany_over_primitive_collection_nested_in_complex_collection_inside_json_column() + => Assert.ThrowsAsync( + base.SelectMany_over_primitive_collection_nested_in_complex_collection_inside_json_column); }