Cosmos: Complex properties model building support for specifying property names#37919
Conversation
There was a problem hiding this comment.
I couldn't find tests for this specifically, so I improvised by creating this to verify everything was working
There was a problem hiding this comment.
Pull request overview
Adds Cosmos provider support for mapping complex properties (and complex-type member properties/collections) to configurable JSON property names, and updates query/update pipelines to respect those names.
Changes:
- Introduces new Cosmos extension APIs to configure JSON property names for complex properties and for properties inside complex types.
- Updates Cosmos query materialization and update document generation to use
GetJsonPropertyName()for complex properties. - Adds functional query tests verifying translation uses renamed JSON property paths.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| test/EFCore.Cosmos.FunctionalTests/Query/ComplexTypeToJsonPropertyQueryCosmosTest.cs | New test coverage validating query translation over renamed complex-property JSON paths. |
| src/EFCore.Cosmos/Update/Internal/DocumentSource.cs | Uses complex property JSON names when creating/updating Cosmos documents. |
| src/EFCore.Cosmos/Query/Internal/Expressions/ObjectArrayAccessExpression.cs | Uses complex property JSON names for array access expressions. |
| src/EFCore.Cosmos/Query/Internal/Expressions/ObjectAccessExpression.cs | Uses complex property JSON names for object access expressions. |
| src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs | Reads complex properties/collections using configured JSON names during materialization. |
| src/EFCore.Cosmos/Query/Internal/CosmosSerializationUtilities.cs | Serializes complex properties using configured JSON names. |
| src/EFCore.Cosmos/Extensions/CosmosComplexTypePropertyBuilderExtensions.cs | New builder extensions for JSON naming of properties on complex types. |
| src/EFCore.Cosmos/Extensions/CosmosComplexTypePrimitiveCollectionBuilderExtensions.cs | New builder extensions for JSON naming of primitive collections on complex types. |
| src/EFCore.Cosmos/Extensions/CosmosComplexPropertyExtensions.cs | New metadata extensions for getting/setting complex property JSON names. |
| src/EFCore.Cosmos/Extensions/CosmosComplexPropertyBuilderExtensions.cs | New builder extensions for JSON naming of complex properties. |
| src/EFCore.Cosmos/Extensions/CosmosComplexCollectionTypePropertyBuilderExtensions.cs | New builder extensions for JSON naming of complex collection type properties. |
| src/EFCore.Cosmos/Extensions/CosmosComplexCollectionBuilderExtensions.cs | New builder extensions for JSON naming of complex collections. |
Comments suppressed due to low confidence (3)
src/EFCore.Cosmos/Update/Internal/DocumentSource.cs:296
- UpdateDocument has the same issue as CreateDocument: if a complex property is configured with an empty JSON name, this will update/remove document[""] rather than treating the complex property as non-persisted. Align this with the scalar-property path (storeName.Length != 0) by skipping complex properties with empty JSON names (and handling deletions consistently).
foreach (var complexProperty in structuralType.GetComplexProperties())
{
var embeddedValue = entry.GetCurrentValue(complexProperty);
var embeddedPropertyName = complexProperty.GetJsonPropertyName();
if (embeddedValue == null)
{
if (document[embeddedPropertyName] != null)
{
document[embeddedPropertyName] = null;
anyPropertyUpdated = true;
src/EFCore.Cosmos/Update/Internal/DocumentSource.cs:154
- Complex properties can now have a custom JSON property name (including the empty string). Unlike scalar properties (which skip persistence when the JSON name is empty), this code always writes to document[embeddedPropertyName]; if embeddedPropertyName is "" this will create an empty-key property instead of treating it as non-persisted. Consider mirroring the scalar-property behavior by skipping complex properties when the JSON name is empty (and ensuring any required default/null behavior is applied).
foreach (var complexProperty in structuralType.GetComplexProperties())
{
var embeddedValue = entry.GetCurrentValue(complexProperty);
var embeddedPropertyName = complexProperty.GetJsonPropertyName();
if (embeddedValue == null)
{
document[embeddedPropertyName] = null;
}
src/EFCore.Cosmos/Query/Internal/CosmosSerializationUtilities.cs:90
- If a complex property is configured with an empty JSON name, this will emit a JSON object with an empty-string key. Scalar properties treat empty JSON names as non-persisted (see other Cosmos JSON name handling); consider skipping complex properties when jsonPropertyName.Length == 0 to avoid generating invalid/unexpected JSON payloads.
foreach (var complexProperty in type.GetComplexProperties())
{
var jsonPropertyName = complexProperty.GetJsonPropertyName();
var propertyValue = complexProperty.GetGetter().GetClrValue(value);
if (propertyValue is null)
{
if (!complexProperty.IsNullable)
{
throw new InvalidOperationException(CoreStrings.PropertyConceptualNull(complexProperty.Name, type.DisplayName()));
}
obj[jsonPropertyName] = null;
}
You can also share your feedback on Copilot code review. Take the survey.
src/EFCore.Cosmos/Extensions/CosmosComplexTypePropertyBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexCollectionBuilderExtensions.cs
Show resolved
Hide resolved
src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexTypePrimitiveCollectionBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexCollectionTypePropertyBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexPropertyBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Cosmos/Query/Internal/Expressions/ObjectArrayAccessExpression.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ithub.com/JoasE/efcore into feature/complex-properties-model-building
ddf52a2 to
796b6b2
Compare
There was a problem hiding this comment.
Pull request overview
Adds Cosmos model-building support for configuring JSON property names on complex properties (and related builders), and updates query/update paths to honor those names—while matching owned-type behavior by disallowing empty names for complex properties.
Changes:
- Introduces new Cosmos extension methods for complex property/complex type builders to configure JSON property names.
- Updates Cosmos query and update pipelines to use configured JSON property names for complex properties.
- Adds functional test coverage for renamed complex-property JSON paths and for non-persisted scalar properties inside complex/owned types.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/EFCore.Cosmos.FunctionalTests/Query/ComplexTypeToJsonPropertyQueryCosmosTest.cs | New query test baselines asserting renamed JSON paths for complex/nested complex properties. |
| test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs | Adds tests for non-persisted scalar properties on owned and complex types; adjusts warning configuration. |
| src/EFCore.Cosmos/Update/Internal/DocumentSource.cs | Persists complex properties using configured JSON property names. |
| src/EFCore.Cosmos/Query/Internal/Expressions/ObjectArrayAccessExpression.cs | Uses configured JSON property names for complex-property array access paths. |
| src/EFCore.Cosmos/Query/Internal/Expressions/ObjectAccessExpression.cs | Uses configured JSON property names for complex-property access paths. |
| src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs | Materialization reads complex properties/collections via configured JSON property names. |
| src/EFCore.Cosmos/Query/Internal/CosmosSerializationUtilities.cs | Skips non-persisted scalar properties during complex-property constant serialization; uses configured JSON names for complex properties. |
| src/EFCore.Cosmos/Extensions/CosmosComplexTypePropertyBuilderExtensions.cs | New ToJsonProperty for scalar properties inside complex types. |
| src/EFCore.Cosmos/Extensions/CosmosComplexTypePrimitiveCollectionBuilderExtensions.cs | New ToJsonProperty for primitive collections inside complex types. |
| src/EFCore.Cosmos/Extensions/CosmosComplexPropertyExtensions.cs | New metadata extensions to get/set JSON name for complex properties (disallow empty). |
| src/EFCore.Cosmos/Extensions/CosmosComplexPropertyBuilderExtensions.cs | New ToJsonProperty for complex properties (embedded document parent name). |
| src/EFCore.Cosmos/Extensions/CosmosComplexCollectionTypePropertyBuilderExtensions.cs | New ToJsonProperty for complex-collection type property builder (name validation differs from docs). |
| src/EFCore.Cosmos/Extensions/CosmosComplexCollectionBuilderExtensions.cs | New ToJsonProperty for complex collection builder (doc typo present). |
You can also share your feedback on Copilot code review. Take the survey.
src/EFCore.Cosmos/Query/Internal/Expressions/ObjectArrayAccessExpression.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexCollectionTypePropertyBuilderExtensions.cs
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexCollectionBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Adds Azure Cosmos model-building support for specifying JSON property names on complex properties/complex types, aligning query/update pipelines and tests with the configured JSON names while disallowing empty names for complex properties.
Changes:
- Use configured JSON property names (
GetJsonPropertyName()) for complex properties across Cosmos query materialization, SQL generation expressions, and update document generation. - Add Cosmos extension APIs for configuring JSON property names on complex properties, complex collections, and scalar properties on complex types (including primitive collections).
- Add/extend functional tests covering renamed complex properties in queries and non-persisted (empty-name) scalar properties inside owned/complex types.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/EFCore.Cosmos.FunctionalTests/Query/ComplexTypeToJsonPropertyQueryCosmosTest.cs | New query test baselines validating SQL uses renamed JSON property names for complex properties. |
| test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs | Adds tests for non-persisted scalar properties (empty JSON name) on owned and complex types; updates warning configuration. |
| src/EFCore.Cosmos/Update/Internal/DocumentSource.cs | Writes embedded complex properties using configured JSON property names when creating/updating documents. |
| src/EFCore.Cosmos/Query/Internal/Expressions/ObjectArrayAccessExpression.cs | Uses configured JSON name for complex-property array access in query translation expressions. |
| src/EFCore.Cosmos/Query/Internal/Expressions/ObjectAccessExpression.cs | Uses configured JSON name for complex-property object access in query translation expressions. |
| src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs | Materializes complex properties/collections via configured JSON property names. |
| src/EFCore.Cosmos/Query/Internal/CosmosSerializationUtilities.cs | Skips non-persisted scalar properties (empty JSON name) during complex-type constant/parameter serialization; uses JSON name for complex properties. |
| src/EFCore.Cosmos/Extensions/CosmosComplexTypePropertyBuilderExtensions.cs | Adds ToJsonProperty for scalar properties on complex types (allows empty to mean non-persisted). |
| src/EFCore.Cosmos/Extensions/CosmosComplexTypePrimitiveCollectionBuilderExtensions.cs | Adds ToJsonProperty for primitive collections on complex types (allows empty to mean non-persisted). |
| src/EFCore.Cosmos/Extensions/CosmosComplexPropertyExtensions.cs | Adds metadata extensions for getting/setting complex-property JSON name (disallows empty, allows null). |
| src/EFCore.Cosmos/Extensions/CosmosComplexPropertyBuilderExtensions.cs | Adds fluent API to set complex-property JSON name (disallows empty via metadata setter). |
| src/EFCore.Cosmos/Extensions/CosmosComplexCollectionBuilderExtensions.cs | Adds fluent API to set complex-collection JSON name (disallows empty via metadata setter). |
| src/EFCore.Cosmos/Extensions/CosmosComplexCollectionTypePropertyBuilderExtensions.cs | Adds ToJsonProperty for scalar properties within complex collections (currently disallows empty). |
You can also share your feedback on Copilot code review. Take the survey.
src/EFCore.Cosmos/Extensions/CosmosComplexCollectionTypePropertyBuilderExtensions.cs
Show resolved
Hide resolved
|
@AndriySvyryd I think this is more in your area, but definitely ping me if you want my eyes on something. |
src/EFCore.Cosmos/Extensions/CosmosComplexCollectionBuilderExtensions.cs
Show resolved
Hide resolved
src/EFCore.Cosmos/Extensions/CosmosComplexTypePropertyBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
|
Thanks for your contribution! |
Part of: #31253
Don't allow empty property names for complex properties (same as owned)
Does allow empty (non-persisted) property names for scalar properties on complex types (same as scalar on owned)