Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
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,
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
{
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()
?? 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()),

_ => 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();
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 @@ -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