Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ public static class RelationalComplexPropertyExtensions
/// <see langword="null" /> is returned for complex properties of entities that are not mapped to a JSON column.
/// </returns>
public static string? GetJsonPropertyName(this IReadOnlyComplexProperty complexProperty)
=> (string?)complexProperty.FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.Value
?? (complexProperty.DeclaringType.IsMappedToJson() ? complexProperty.Name : null);
=> complexProperty.ComplexType.GetJsonPropertyName();

/// <summary>
/// Sets the value of JSON property name used for the given complex property of an entity mapped to a JSON column.
/// </summary>
/// <param name="complexProperty">The complex property.</param>
/// <param name="name">The name to be used.</param>
public static void SetJsonPropertyName(this IMutableComplexProperty complexProperty, string? name)
=> complexProperty.SetOrRemoveAnnotation(
=> ((IMutableTypeBase)complexProperty.ComplexType).SetOrRemoveAnnotation(
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
RelationalAnnotationNames.JsonPropertyName,
Check.NullButNotEmpty(name));

Expand All @@ -47,7 +46,7 @@ public static void SetJsonPropertyName(this IMutableComplexProperty complexPrope
this IConventionComplexProperty complexProperty,
string? name,
bool fromDataAnnotation = false)
=> (string?)complexProperty.SetOrRemoveAnnotation(
=> (string?)((IConventionTypeBase)complexProperty.ComplexType).SetOrRemoveAnnotation(
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
RelationalAnnotationNames.JsonPropertyName,
Check.NullButNotEmpty(name),
fromDataAnnotation)?.Value;
Expand All @@ -58,5 +57,5 @@ public static void SetJsonPropertyName(this IMutableComplexProperty complexPrope
/// <param name="complexProperty">The complex property.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the JSON property name for a given complex property.</returns>
public static ConfigurationSource? GetJsonPropertyNameConfigurationSource(this IConventionComplexProperty complexProperty)
=> complexProperty.FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.GetConfigurationSource();
=> ((IConventionTypeBase)complexProperty.ComplexType).FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.GetConfigurationSource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,9 @@ public static void SetContainerColumnType(this IMutableTypeBase typeBase, string
? null
: typeBase is IReadOnlyEntityType entityType
? entityType.FindOwnership()!.GetNavigation(pointsToPrincipal: false)!.Name
: ((IReadOnlyComplexType)typeBase).ComplexProperty.Name);
: typeBase.FindAnnotation(RelationalAnnotationNames.ContainerColumnName) != null
? null
: ((IReadOnlyComplexType)typeBase).ComplexProperty.Name);
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated

#endregion
}
5 changes: 2 additions & 3 deletions src/EFCore.Relational/Query/JsonQueryExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,11 @@ public virtual JsonQueryExpression BindStructuralProperty(IPropertyBase structur

Check.DebugAssert(KeyPropertyMap is null);

var targetComplexType = complexProperty.ComplexType;
var newPath = Path.ToList();
newPath.Add(new PathSegment(targetComplexType.GetJsonPropertyName()!));
newPath.Add(new PathSegment(complexProperty.GetJsonPropertyName()!));

return new JsonQueryExpression(
targetComplexType,
complexProperty.ComplexType,
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
JsonColumn,
keyPropertyMap: null,
newPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1628,10 +1628,10 @@ private Expression CreateJsonShapers(
nestedStructuralProperty is not IComplexProperty { ComplexType: var complexType } || complexType.IsMappedToJson(),
"Non-JSON complex type within JSON complex type");

var (relatedStructuralType, inverseNavigation, isStructuralPropertyNullable) = nestedStructuralProperty switch
var (relatedStructuralType, navigationJsonPropertyName, inverseNavigation, isStructuralPropertyNullable) = nestedStructuralProperty switch
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
{
INavigation n => ((ITypeBase)n.TargetEntityType, n.Inverse, !n.ForeignKey.IsRequiredDependent),
IComplexProperty cp => (cp.ComplexType, null, cp.IsNullable),
INavigation n => ((ITypeBase)n.TargetEntityType, n.TargetEntityType.GetJsonPropertyName()!, n.Inverse, !n.ForeignKey.IsRequiredDependent),
IComplexProperty cp => (cp.ComplexType, cp.GetJsonPropertyName()!, null, cp.IsNullable),

_ => throw new UnreachableException()
};
Expand All @@ -1645,7 +1645,6 @@ private Expression CreateJsonShapers(
containerEntityExpression: null,
nestedStructuralProperty);

var navigationJsonPropertyName = relatedStructuralType.GetJsonPropertyName()!;
innerShapersMap[navigationJsonPropertyName] = innerShaper;

if (nestedStructuralProperty.IsCollection)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2895,7 +2895,7 @@ public static Expression GenerateComplexPropertyShaperExpression(
// Otherwise, if the source type isn't mapped to JSON, we're just binding to an actual JSON column in a relational table, and not within it.
var containerColumnExpression = complexProperty.DeclaringType.IsMappedToJson()
? new ColumnExpression(
complexType.GetJsonPropertyName()
complexProperty.GetJsonPropertyName()
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
?? throw new UnreachableException($"No JSON property name for complex property {complexProperty.Name}"),
tableAlias,
complexProperty.ClrType.UnwrapNullableType(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ IEntityType entityType
.Select(n => n.TargetEntityType.GetJsonPropertyName() ?? throw new UnreachableException()),

IComplexType complexType
=> complexType.GetComplexProperties().Select(p => p.ComplexType.GetJsonPropertyName() ?? throw new UnreachableException()),
=> complexType.GetComplexProperties().Select(p => p.GetJsonPropertyName() ?? throw new UnreachableException()),
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated

_ => throw new UnreachableException()
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ [new PathSegment(jsonNavigationName)],

foreach (var complexProperty in structuralType.GetComplexProperties())
{
var jsonNavigationName = complexProperty.ComplexType.GetJsonPropertyName();
var jsonNavigationName = complexProperty.GetJsonPropertyName();
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
Check.DebugAssert(jsonNavigationName is not null, "Invalid complex property found on JSON-mapped structural type");

var projectionMember = new ProjectionMember().Append(new FakeMemberInfo(jsonNavigationName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,16 @@ public virtual void ComplexCollection_can_have_nested_complex_properties_mapped_

var nestedCol3 = complexCollectionProperty1.ComplexType.FindComplexProperty("Collection1")!;
Assert.Equal("CustomNestedCollection3", nestedCol3.GetJsonPropertyName());

// Verify that no complex properties have the JsonPropertyName annotation directly
foreach (var complexProperty in entityType.GetComplexProperties())
{
Assert.Null(complexProperty.FindAnnotation(RelationalAnnotationNames.JsonPropertyName));
foreach (var nestedComplexProperty in complexProperty.ComplexType.GetComplexProperties())
{
Assert.Null(nestedComplexProperty.FindAnnotation(RelationalAnnotationNames.JsonPropertyName));
}
}
}

[ConditionalFact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,79 @@ public class JsonEntity

#endregion

#region HasJsonPropertyName

[ConditionalFact]
public virtual async Task HasJsonPropertyName()
{
var contextFactory = await InitializeAsync<Context37009>(
onConfiguring: b => b.ConfigureWarnings(ConfigureWarnings),
onModelCreating: m => m.Entity<Context37009.Entity>().ComplexProperty(e => e.Json, b =>
{
b.ToJson();

b.Property(j => j.String).HasJsonPropertyName("string");

b.ComplexProperty(j => j.Nested, b =>
{
b.HasJsonPropertyName("nested");
b.Property(x => x.Int).HasJsonPropertyName("int");
});

b.ComplexCollection(a => a.NestedCollection, b =>
{
b.HasJsonPropertyName("nested_collection");
b.Property(x => x.Int).HasJsonPropertyName("int");
});
}),
seed: context =>
{
context.Set<Context37009.Entity>().Add(new Context37009.Entity
{
Json = new Context37009.JsonComplexType
{
String = "foo",
Nested = new Context37009.JsonNestedType { Int = 1 },
NestedCollection = [new Context37009.JsonNestedType { Int = 2 }]
}
});

return context.SaveChangesAsync();
});

await using var context = contextFactory.CreateContext();

Assert.Equal(1, await context.Set<Context37009.Entity>().CountAsync(e => e.Json.String == "foo"));
Assert.Equal(1, await context.Set<Context37009.Entity>().CountAsync(e => e.Json.Nested.Int == 1));
Assert.Equal(1, await context.Set<Context37009.Entity>().CountAsync(e => e.Json.NestedCollection.Any(x => x.Int == 2)));
}

protected class Context37009(DbContextOptions options) : DbContext(options)
{
public DbSet<Entity> Entities { get; set; }

public class Entity
{
public int Id { get; set; }
public JsonComplexType Json { get; set; }
}

public class JsonComplexType
{
public string String { get; set; }

public JsonNestedType Nested { get; set; }
public List<JsonNestedType> NestedCollection { get; set; }
}

public class JsonNestedType
{
public int Int { get; set; }
}
}

#endregion HasJsonPropertyName

protected TestSqlLoggerFactory TestSqlLoggerFactory
=> (TestSqlLoggerFactory)ListLoggerFactory;

Expand Down
Loading