diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
index 9930786970e..a1782ffba8b 100644
--- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
@@ -22,8 +22,6 @@ public class SqlServerQueryableMethodTranslatingExpressionVisitor : RelationalQu
private readonly ISqlExpressionFactory _sqlExpressionFactory;
private readonly ISqlServerSingletonOptions _sqlServerSingletonOptions;
- private RelationalTypeMapping? _nvarcharMaxTypeMapping;
-
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -239,6 +237,8 @@ protected override Expression VisitExtension(Expression extensionExpression)
///
protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpression jsonQueryExpression)
{
+ var structuralType = jsonQueryExpression.StructuralType;
+
// Calculate the table alias for the OPENJSON expression based on the last named path segment
// (or the JSON column name if there are none)
var lastNamedPathSegment = jsonQueryExpression.Path.LastOrDefault(ps => ps.PropertyName is not null);
@@ -251,7 +251,8 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr
var columnInfos = new List();
// We're only interested in properties which actually exist in the JSON, filter out uninteresting shadow keys
- foreach (var property in jsonQueryExpression.StructuralType.GetPropertiesInHierarchy())
+ // (for owned JSON entities)
+ foreach (var property in structuralType.GetPropertiesInHierarchy())
{
if (property.GetJsonPropertyName() is { } jsonPropertyName)
{
@@ -266,46 +267,40 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr
}
}
- switch (jsonQueryExpression.StructuralType)
+ // Find the container column in the relational model to get its type mapping
+ // Note that we assume exactly one column with the given name mapped to the entity (despite entity splitting).
+ // See #36647 and #36646 about improving this.
+ var containerColumnName = structuralType.GetContainerColumnName();
+ var containerColumn = structuralType.ContainingEntityType.GetTableMappings()
+ .SelectMany(m => m.Table.Columns)
+ .Where(c => c.Name == containerColumnName)
+ .Single();
+
+ var nestedJsonPropertyNames = jsonQueryExpression.StructuralType switch
{
- case IEntityType entityType:
- // Navigations represent nested JSON owned entities, which we also add to the OPENJSON WITH clause, but with AS JSON.
- foreach (var navigation in entityType.GetNavigationsInHierarchy()
- .Where(n => n.ForeignKey.IsOwnership
- && n.TargetEntityType.IsMappedToJson()
- && n.ForeignKey.PrincipalToDependent == n))
- {
- var jsonPropertyName = navigation.TargetEntityType.GetJsonPropertyName();
- Check.DebugAssert(jsonPropertyName is not null, $"No JSON property name for navigation {navigation.Name}");
+ IEntityType entityType
+ => entityType.GetNavigationsInHierarchy()
+ .Where(n => n.ForeignKey.IsOwnership
+ && n.TargetEntityType.IsMappedToJson()
+ && n.ForeignKey.PrincipalToDependent == n)
+ .Select(n => n.TargetEntityType.GetJsonPropertyName() ?? throw new UnreachableException()),
- AddStructuralColumnInfo(jsonPropertyName);
- }
+ IComplexType complexType
+ => complexType.GetComplexProperties().Select(p => p.ComplexType.GetJsonPropertyName() ?? throw new UnreachableException()),
- break;
+ _ => throw new UnreachableException()
+ };
- case IComplexType complexType:
- foreach (var complexProperty in complexType.GetComplexProperties())
+ foreach (var jsonPropertyName in nestedJsonPropertyNames)
+ {
+ columnInfos.Add(
+ new SqlServerOpenJsonExpression.ColumnInfo
{
- var jsonPropertyName = complexProperty.ComplexType.GetJsonPropertyName();
- Check.DebugAssert(jsonPropertyName is not null, $"No JSON property name for complex property {complexProperty.Name}");
-
- AddStructuralColumnInfo(jsonPropertyName);
- }
-
- break;
-
- default:
- throw new UnreachableException();
-
- void AddStructuralColumnInfo(string jsonPropertyName)
- => columnInfos.Add(
- new SqlServerOpenJsonExpression.ColumnInfo
- {
- Name = jsonPropertyName,
- TypeMapping = _nvarcharMaxTypeMapping ??= _typeMappingSource.FindMapping("nvarchar(max)")!,
- Path = [new PathSegment(jsonPropertyName)],
- AsJson = true
- });
+ Name = jsonPropertyName,
+ TypeMapping = containerColumn.StoreTypeMapping,
+ Path = [new PathSegment(jsonPropertyName)],
+ AsJson = true
+ });
}
var openJsonExpression = new SqlServerOpenJsonExpression(
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonCollectionSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonCollectionSqlServerTest.cs
index 59d1597e9d9..85109be2ba2 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonCollectionSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonCollectionSqlServerTest.cs
@@ -3,6 +3,8 @@
namespace Microsoft.EntityFrameworkCore.Query.Associations.ComplexJson;
+using Microsoft.Data.SqlClient;
+
public class ComplexJsonCollectionSqlServerTest(ComplexJsonSqlServerFixture fixture, ITestOutputHelper testOutputHelper)
: ComplexJsonCollectionRelationalTestBase(fixture, testOutputHelper)
{
@@ -58,10 +60,37 @@ ORDER BY [r0].[Id]
public override async Task Distinct()
{
- await base.Distinct();
+ if (Fixture.UsingJsonType)
+ {
+ // The json data type cannot be selected as DISTINCT because it is not comparable.
+ await Assert.ThrowsAsync(base.Distinct);
- AssertSql(
- """
+ AssertSql(
+ """
+SELECT [r].[Id], [r].[Name], [r].[OptionalRelated], [r].[RelatedCollection], [r].[RequiredRelated]
+FROM [RootEntity] AS [r]
+WHERE (
+ SELECT COUNT(*)
+ FROM (
+ SELECT DISTINCT [r0].[Id], [r0].[Int], [r0].[Name], [r0].[String], [r0].[NestedCollection] AS [c], [r0].[OptionalNested] AS [c0], [r0].[RequiredNested] AS [c1]
+ FROM OPENJSON([r].[RelatedCollection], '$') WITH (
+ [Id] int '$.Id',
+ [Int] int '$.Int',
+ [Name] nvarchar(max) '$.Name',
+ [String] nvarchar(max) '$.String',
+ [NestedCollection] json '$.NestedCollection' AS JSON,
+ [OptionalNested] json '$.OptionalNested' AS JSON,
+ [RequiredNested] json '$.RequiredNested' AS JSON
+ ) AS [r0]
+ ) AS [r1]) = 2
+""");
+ }
+ else
+ {
+ await base.Distinct();
+
+ AssertSql(
+ """
SELECT [r].[Id], [r].[Name], [r].[OptionalRelated], [r].[RelatedCollection], [r].[RequiredRelated]
FROM [RootEntity] AS [r]
WHERE (
@@ -79,6 +108,7 @@ [RequiredNested] nvarchar(max) '$.RequiredNested' AS JSON
) AS [r0]
) AS [r1]) = 2
""");
+ }
}
public override async Task Distinct_projected(QueryTrackingBehavior queryTrackingBehavior)
@@ -90,10 +120,29 @@ public override async Task Distinct_projected(QueryTrackingBehavior queryTrackin
public override async Task Distinct_over_projected_nested_collection()
{
- await base.Distinct_over_projected_nested_collection();
+ if (Fixture.UsingJsonType)
+ {
+ // The json data type cannot be selected as DISTINCT because it is not comparable.
+ await Assert.ThrowsAsync(base.Distinct_over_projected_nested_collection);
- AssertSql(
- """
+ AssertSql(
+ """
+SELECT [r].[Id], [r].[Name], [r].[OptionalRelated], [r].[RelatedCollection], [r].[RequiredRelated]
+FROM [RootEntity] AS [r]
+WHERE (
+ SELECT COUNT(*)
+ FROM (
+ SELECT DISTINCT [r0].[NestedCollection] AS [c]
+ FROM OPENJSON([r].[RelatedCollection], '$') WITH ([NestedCollection] json '$.NestedCollection' AS JSON) AS [r0]
+ ) AS [r1]) = 2
+""");
+ }
+ else
+ {
+ await base.Distinct_over_projected_nested_collection();
+
+ AssertSql(
+ """
SELECT [r].[Id], [r].[Name], [r].[OptionalRelated], [r].[RelatedCollection], [r].[RequiredRelated]
FROM [RootEntity] AS [r]
WHERE (
@@ -103,6 +152,7 @@ SELECT DISTINCT [r0].[NestedCollection] AS [c]
FROM OPENJSON([r].[RelatedCollection], '$') WITH ([NestedCollection] nvarchar(max) '$.NestedCollection' AS JSON) AS [r0]
) AS [r1]) = 2
""");
+ }
}
public override async Task Distinct_over_projected_filtered_nested_collection()
@@ -246,8 +296,24 @@ public override async Task Select_within_Select_within_Select_with_aggregates()
{
await base.Select_within_Select_within_Select_with_aggregates();
- AssertSql(
- """
+ if (Fixture.UsingJsonType)
+ {
+ AssertSql(
+ """
+SELECT (
+ SELECT COALESCE(SUM([s].[value]), 0)
+ FROM OPENJSON([r].[RelatedCollection], '$') WITH ([NestedCollection] json '$.NestedCollection' AS JSON) AS [r0]
+ OUTER APPLY (
+ SELECT MAX([n].[Int]) AS [value]
+ FROM OPENJSON([r0].[NestedCollection], '$') WITH ([Int] int '$.Int') AS [n]
+ ) AS [s])
+FROM [RootEntity] AS [r]
+""");
+ }
+ else
+ {
+ AssertSql(
+ """
SELECT (
SELECT COALESCE(SUM([s].[value]), 0)
FROM OPENJSON([r].[RelatedCollection], '$') WITH ([NestedCollection] nvarchar(max) '$.NestedCollection' AS JSON) AS [r0]
@@ -257,6 +323,7 @@ FROM OPENJSON([r0].[NestedCollection], '$') WITH ([Int] int '$.Int') AS [n]
) AS [s])
FROM [RootEntity] AS [r]
""");
+ }
}
[ConditionalFact]
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonProjectionSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonProjectionSqlServerTest.cs
index 450950230ed..c6be3eb5a80 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonProjectionSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonProjectionSqlServerTest.cs
@@ -233,8 +233,27 @@ public override async Task SelectMany_related_collection(QueryTrackingBehavior q
{
await base.SelectMany_related_collection(queryTrackingBehavior);
- AssertSql(
- """
+ if (Fixture.UsingJsonType)
+ {
+ AssertSql(
+ """
+SELECT [r0].[Id], [r0].[Int], [r0].[Name], [r0].[String], [r0].[NestedCollection], [r0].[OptionalNested], [r0].[RequiredNested]
+FROM [RootEntity] AS [r]
+CROSS APPLY OPENJSON([r].[RelatedCollection], '$') WITH (
+ [Id] int '$.Id',
+ [Int] int '$.Int',
+ [Name] nvarchar(max) '$.Name',
+ [String] nvarchar(max) '$.String',
+ [NestedCollection] json '$.NestedCollection' AS JSON,
+ [OptionalNested] json '$.OptionalNested' AS JSON,
+ [RequiredNested] json '$.RequiredNested' AS JSON
+) AS [r0]
+""");
+ }
+ else
+ {
+ AssertSql(
+ """
SELECT [r0].[Id], [r0].[Int], [r0].[Name], [r0].[String], [r0].[NestedCollection], [r0].[OptionalNested], [r0].[RequiredNested]
FROM [RootEntity] AS [r]
CROSS APPLY OPENJSON([r].[RelatedCollection], '$') WITH (
@@ -247,6 +266,7 @@ [OptionalNested] nvarchar(max) '$.OptionalNested' AS JSON,
[RequiredNested] nvarchar(max) '$.RequiredNested' AS JSON
) AS [r0]
""");
+ }
}
public override async Task SelectMany_nested_collection_on_required_related(QueryTrackingBehavior queryTrackingBehavior)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonSetOperationsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonSetOperationsSqlServerTest.cs
index 1fa5604b5b3..1b093ec29c7 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonSetOperationsSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonSetOperationsSqlServerTest.cs
@@ -39,8 +39,38 @@ public override async Task On_related_Select_nested_with_aggregates(QueryTrackin
{
await base.On_related_Select_nested_with_aggregates(queryTrackingBehavior);
- AssertSql(
- """
+ if (Fixture.UsingJsonType)
+ {
+ AssertSql(
+ """
+SELECT (
+ SELECT COALESCE(SUM([s].[value]), 0)
+ FROM (
+ SELECT [r0].[NestedCollection] AS [NestedCollection]
+ FROM OPENJSON([r].[RelatedCollection], '$') WITH (
+ [Int] int '$.Int',
+ [NestedCollection] json '$.NestedCollection' AS JSON
+ ) AS [r0]
+ WHERE [r0].[Int] = 8
+ UNION ALL
+ SELECT [r1].[NestedCollection] AS [NestedCollection]
+ FROM OPENJSON([r].[RelatedCollection], '$') WITH (
+ [String] nvarchar(max) '$.String',
+ [NestedCollection] json '$.NestedCollection' AS JSON
+ ) AS [r1]
+ WHERE [r1].[String] = N'foo'
+ ) AS [u]
+ OUTER APPLY (
+ SELECT COALESCE(SUM([n].[Int]), 0) AS [value]
+ FROM OPENJSON([u].[NestedCollection], '$') WITH ([Int] int '$.Int') AS [n]
+ ) AS [s])
+FROM [RootEntity] AS [r]
+""");
+ }
+ else
+ {
+ AssertSql(
+ """
SELECT (
SELECT COALESCE(SUM([s].[value]), 0)
FROM (
@@ -64,6 +94,7 @@ FROM OPENJSON([u].[NestedCollection], '$') WITH ([Int] int '$.Int') AS [n]
) AS [s])
FROM [RootEntity] AS [r]
""");
+ }
}
public override async Task On_nested()
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonStructuralEqualitySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonStructuralEqualitySqlServerTest.cs
index 0137526254e..0d4eb695dff 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonStructuralEqualitySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/Associations/ComplexJson/ComplexJsonStructuralEqualitySqlServerTest.cs
@@ -341,8 +341,39 @@ public override async Task Contains_with_nested_and_composed_operators()
{
await base.Contains_with_nested_and_composed_operators();
- AssertSql(
- """
+ if (Fixture.UsingJsonType)
+ {
+ AssertSql(
+ """
+@get_Item_Id='?' (DbType = Int32)
+@entity_equality_get_Item_Id='?' (DbType = Int32)
+@entity_equality_get_Item_Int='?' (DbType = Int32)
+@entity_equality_get_Item_Name='?' (Size = 4000)
+@entity_equality_get_Item_String='?' (Size = 4000)
+@entity_equality_get_Item_NestedCollection='?' (Size = 195)
+@entity_equality_get_Item_OptionalNested='?' (Size = 89)
+@entity_equality_get_Item_RequiredNested='?' (Size = 89)
+
+SELECT [r].[Id], [r].[Name], [r].[OptionalRelated], [r].[RelatedCollection], [r].[RequiredRelated]
+FROM [RootEntity] AS [r]
+WHERE EXISTS (
+ SELECT 1
+ FROM OPENJSON([r].[RelatedCollection], '$') WITH (
+ [Id] int '$.Id',
+ [Int] int '$.Int',
+ [Name] nvarchar(max) '$.Name',
+ [String] nvarchar(max) '$.String',
+ [NestedCollection] json '$.NestedCollection' AS JSON,
+ [OptionalNested] json '$.OptionalNested' AS JSON,
+ [RequiredNested] json '$.RequiredNested' AS JSON
+ ) AS [r0]
+ WHERE [r0].[Id] > @get_Item_Id AND [r0].[Id] = @entity_equality_get_Item_Id AND [r0].[Int] = @entity_equality_get_Item_Int AND [r0].[Name] = @entity_equality_get_Item_Name AND [r0].[String] = @entity_equality_get_Item_String AND CAST([r0].[NestedCollection] AS nvarchar(max)) = CAST(@entity_equality_get_Item_NestedCollection AS nvarchar(max)) AND CAST([r0].[OptionalNested] AS nvarchar(max)) = CAST(@entity_equality_get_Item_OptionalNested AS nvarchar(max)) AND CAST([r0].[RequiredNested] AS nvarchar(max)) = CAST(@entity_equality_get_Item_RequiredNested AS nvarchar(max)))
+""");
+ }
+ else
+ {
+ AssertSql(
+ """
@get_Item_Id='?' (DbType = Int32)
@entity_equality_get_Item_Id='?' (DbType = Int32)
@entity_equality_get_Item_Int='?' (DbType = Int32)
@@ -367,6 +398,7 @@ [RequiredNested] nvarchar(max) '$.RequiredNested' AS JSON
) AS [r0]
WHERE [r0].[Id] > @get_Item_Id AND [r0].[Id] = @entity_equality_get_Item_Id AND [r0].[Int] = @entity_equality_get_Item_Int AND [r0].[Name] = @entity_equality_get_Item_Name AND [r0].[String] = @entity_equality_get_Item_String AND [r0].[NestedCollection] = @entity_equality_get_Item_NestedCollection AND [r0].[OptionalNested] = @entity_equality_get_Item_OptionalNested AND [r0].[RequiredNested] = @entity_equality_get_Item_RequiredNested)
""");
+ }
}
#endregion Contains
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/JsonQueryJsonTypeSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/JsonQueryJsonTypeSqlServerTest.cs
index ea72e060763..f38e57a7dc8 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/JsonQueryJsonTypeSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/JsonQueryJsonTypeSqlServerTest.cs
@@ -1067,7 +1067,6 @@ FROM [JsonEntitiesBasic] AS [j]
""");
}
- [ConditionalTheory(Skip = "#36628")]
public override async Task Json_collection_Any_with_predicate(bool async)
{
await base.Json_collection_Any_with_predicate(async);
@@ -1078,7 +1077,7 @@ public override async Task Json_collection_Any_with_predicate(bool async)
FROM [JsonEntitiesBasic] AS [j]
WHERE EXISTS (
SELECT 1
- FROM OPENJSON([j].[OwnedReferenceRoot], '$.OwnedCollectionBranch') WITH ([OwnedReferenceLeaf] nvarchar(max) '$.OwnedReferenceLeaf' AS JSON) AS [o]
+ FROM OPENJSON([j].[OwnedReferenceRoot], '$.OwnedCollectionBranch') WITH ([OwnedReferenceLeaf] json '$.OwnedReferenceLeaf' AS JSON) AS [o]
WHERE JSON_VALUE([o].[OwnedReferenceLeaf], '$.SomethingSomething' RETURNING nvarchar(max)) = N'e1_r_c1_r')
""");
}
@@ -1121,7 +1120,6 @@ ORDER BY [o0].[c0]
""");
}
- [ConditionalTheory(Skip = "#36628")]
public override async Task Json_collection_OrderByDescending_Skip_ElementAt(bool async)
{
await base.Json_collection_OrderByDescending_Skip_ElementAt(async);
@@ -1133,12 +1131,13 @@ FROM [JsonEntitiesBasic] AS [j]
WHERE (
SELECT [o0].[c]
FROM (
- SELECT JSON_VALUE([o].[OwnedReferenceLeaf], '$.SomethingSomething') AS [c], [o].[Date] AS [c0]
- FROM OPENJSON(CAST([j].[OwnedReferenceRoot] AS nvarchar(max)), '$.OwnedCollectionBranch') WITH (
+ SELECT JSON_VALUE([o].[OwnedReferenceLeaf], '$.SomethingSomething' RETURNING nvarchar(max)) AS [c], [o].[Date] AS [c0]
+ FROM OPENJSON([j].[OwnedReferenceRoot], '$.OwnedCollectionBranch') WITH (
[Date] datetime2 '$.Date',
[Enum] int '$.Enum',
[Fraction] decimal(18,2) '$.Fraction',
- [OwnedReferenceLeaf] nvarchar(max) '$.OwnedReferenceLeaf' AS JSON
+ [Id] int '$.Id',
+ [OwnedReferenceLeaf] json '$.OwnedReferenceLeaf' AS JSON
) AS [o]
ORDER BY [o].[Date] DESC
OFFSET 1 ROWS
@@ -1148,10 +1147,12 @@ ORDER BY [o0].[c0] DESC
""");
}
- [ConditionalTheory(Skip = "#36628")]
public override async Task Json_collection_Distinct_Count_with_predicate(bool async)
{
- await base.Json_collection_Distinct_Count_with_predicate(async);
+ // TODO:SQLJSON Json type is not comparable
+ Assert.Equal(
+ "The json data type cannot be selected as DISTINCT because it is not comparable.\nThe json data type cannot be selected as DISTINCT because it is not comparable.",
+ (await Assert.ThrowsAsync(() => base.Json_collection_Distinct_Count_with_predicate(async))).Message);
AssertSql(
"""
@@ -1160,18 +1161,19 @@ FROM [JsonEntitiesBasic] AS [j]
WHERE (
SELECT COUNT(*)
FROM (
- SELECT DISTINCT [j].[Id], [o].[Date], [o].[Enum], [o].[Enums], [o].[Fraction], [o].[NullableEnum], [o].[NullableEnums], [o].[OwnedCollectionLeaf] AS [c], [o].[OwnedReferenceLeaf] AS [c0]
- FROM OPENJSON(CAST([j].[OwnedReferenceRoot] AS nvarchar(max)), '$.OwnedCollectionBranch') WITH (
+ SELECT DISTINCT [j].[Id], [o].[Date], [o].[Enum], [o].[Enums], [o].[Fraction], [o].[Id] AS [Id0], [o].[NullableEnum], [o].[NullableEnums], [o].[OwnedCollectionLeaf] AS [c], [o].[OwnedReferenceLeaf] AS [c0]
+ FROM OPENJSON([j].[OwnedReferenceRoot], '$.OwnedCollectionBranch') WITH (
[Date] datetime2 '$.Date',
[Enum] int '$.Enum',
[Enums] nvarchar(max) '$.Enums' AS JSON,
[Fraction] decimal(18,2) '$.Fraction',
+ [Id] int '$.Id',
[NullableEnum] int '$.NullableEnum',
[NullableEnums] nvarchar(max) '$.NullableEnums' AS JSON,
- [OwnedCollectionLeaf] nvarchar(max) '$.OwnedCollectionLeaf' AS JSON,
- [OwnedReferenceLeaf] nvarchar(max) '$.OwnedReferenceLeaf' AS JSON
+ [OwnedCollectionLeaf] json '$.OwnedCollectionLeaf' AS JSON,
+ [OwnedReferenceLeaf] json '$.OwnedReferenceLeaf' AS JSON
) AS [o]
- WHERE JSON_VALUE([o].[OwnedReferenceLeaf], '$.SomethingSomething') = N'e1_r_c2_r'
+ WHERE JSON_VALUE([o].[OwnedReferenceLeaf], '$.SomethingSomething' RETURNING nvarchar(max)) = N'e1_r_c2_r'
) AS [o0]) = 1
""");
}
@@ -1186,7 +1188,7 @@ public override async Task Json_collection_within_collection_Count(bool async)
FROM [JsonEntitiesBasic] AS [j]
WHERE EXISTS (
SELECT 1
- FROM OPENJSON([j].[OwnedCollectionRoot], '$') WITH ([OwnedCollectionBranch] nvarchar(max) '$.OwnedCollectionBranch' AS JSON) AS [o]
+ FROM OPENJSON([j].[OwnedCollectionRoot], '$') WITH ([OwnedCollectionBranch] json '$.OwnedCollectionBranch' AS JSON) AS [o]
WHERE (
SELECT COUNT(*)
FROM OPENJSON([o].[OwnedCollectionBranch], '$') AS [o0]) = 2)
@@ -1365,7 +1367,10 @@ OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY
public override async Task Json_collection_distinct_in_projection(bool async)
{
- await base.Json_collection_distinct_in_projection(async);
+ // TODO:SQLJSON Json type is not comparable
+ Assert.Equal(
+ "The json data type cannot be selected as DISTINCT because it is not comparable.\nThe json data type cannot be selected as DISTINCT because it is not comparable.",
+ (await Assert.ThrowsAsync(() => base.Json_collection_distinct_in_projection(async))).Message);
AssertSql(
"""
@@ -1379,8 +1384,8 @@ [Name] nvarchar(max) '$.Name',
[Names] nvarchar(max) '$.Names' AS JSON,
[Number] int '$.Number',
[Numbers] nvarchar(max) '$.Numbers' AS JSON,
- [OwnedCollectionBranch] nvarchar(max) '$.OwnedCollectionBranch' AS JSON,
- [OwnedReferenceBranch] nvarchar(max) '$.OwnedReferenceBranch' AS JSON
+ [OwnedCollectionBranch] json '$.OwnedCollectionBranch' AS JSON,
+ [OwnedReferenceBranch] json '$.OwnedReferenceBranch' AS JSON
) AS [o]
) AS [o0]
ORDER BY [j].[Id], [o0].[Id0], [o0].[Name], [o0].[Names], [o0].[Number]
@@ -1413,7 +1418,10 @@ WHERE JSON_VALUE([o].[value], '$.SomethingSomething') <> N'Baz' OR JSON_VALUE([o
public override async Task Json_multiple_collection_projections(bool async)
{
- await base.Json_multiple_collection_projections(async);
+ // TODO:SQLJSON Json type is not comparable
+ Assert.Equal(
+ "The json data type cannot be selected as DISTINCT because it is not comparable.\nThe json data type cannot be selected as DISTINCT because it is not comparable.",
+ (await Assert.ThrowsAsync(() => base.Json_multiple_collection_projections(async))).Message);
AssertSql(
"""
@@ -1432,8 +1440,8 @@ [Name] nvarchar(max) '$.Name',
[Names] nvarchar(max) '$.Names' AS JSON,
[Number] int '$.Number',
[Numbers] nvarchar(max) '$.Numbers' AS JSON,
- [OwnedCollectionBranch] nvarchar(max) '$.OwnedCollectionBranch' AS JSON,
- [OwnedReferenceBranch] nvarchar(max) '$.OwnedReferenceBranch' AS JSON
+ [OwnedCollectionBranch] json '$.OwnedCollectionBranch' AS JSON,
+ [OwnedReferenceBranch] json '$.OwnedReferenceBranch' AS JSON
) AS [o0]
) AS [o1]
OUTER APPLY (
@@ -1452,7 +1460,10 @@ WHERE CAST(JSON_VALUE([o3].[value], '$.Date') AS datetime2) <> '2000-01-01T00:00
public override async Task Json_branch_collection_distinct_and_other_collection(bool async)
{
- await base.Json_branch_collection_distinct_and_other_collection(async);
+ // TODO:SQLJSON Json type is not comparable
+ Assert.Equal(
+ "The json data type cannot be selected as DISTINCT because it is not comparable.\nThe json data type cannot be selected as DISTINCT because it is not comparable.",
+ (await Assert.ThrowsAsync(() => base.Json_branch_collection_distinct_and_other_collection(async))).Message);
AssertSql(
"""
@@ -1468,8 +1479,8 @@ [Fraction] decimal(18,2) '$.Fraction',
[Id] int '$.Id',
[NullableEnum] int '$.NullableEnum',
[NullableEnums] nvarchar(max) '$.NullableEnums' AS JSON,
- [OwnedCollectionLeaf] nvarchar(max) '$.OwnedCollectionLeaf' AS JSON,
- [OwnedReferenceLeaf] nvarchar(max) '$.OwnedReferenceLeaf' AS JSON
+ [OwnedCollectionLeaf] json '$.OwnedCollectionLeaf' AS JSON,
+ [OwnedReferenceLeaf] json '$.OwnedReferenceLeaf' AS JSON
) AS [o]
) AS [o0]
LEFT JOIN [JsonEntitiesBasicForCollection] AS [j0] ON [j].[Id] = [j0].[ParentId]