Skip to content

Cosmos: Complex properties model building support for specifying property names#37919

Merged
AndriySvyryd merged 10 commits intodotnet:mainfrom
JoasE:feature/complex-properties-model-building
Mar 17, 2026
Merged

Cosmos: Complex properties model building support for specifying property names#37919
AndriySvyryd merged 10 commits intodotnet:mainfrom
JoasE:feature/complex-properties-model-building

Conversation

@JoasE
Copy link
Contributor

@JoasE JoasE commented Mar 13, 2026

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)

Copy link
Contributor Author

@JoasE JoasE left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be last of #31253
Note that full text and vector is missing, this is due to having no api to define indexes on complex type scalar properties as far as I found.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find tests for this specifically, so I improvised by creating this to verify everything was working

@JoasE JoasE marked this pull request as ready for review March 13, 2026 13:10
@JoasE JoasE requested a review from a team as a code owner March 13, 2026 13:10
Copilot AI review requested due to automatic review settings March 13, 2026 13:10
@JoasE JoasE marked this pull request as draft March 13, 2026 13:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@JoasE JoasE force-pushed the feature/complex-properties-model-building branch from ddf52a2 to 796b6b2 Compare March 15, 2026 19:07
@JoasE JoasE requested a review from Copilot March 15, 2026 19:26
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@JoasE JoasE marked this pull request as ready for review March 15, 2026 19:57
Copilot AI review requested due to automatic review settings March 15, 2026 19:57
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@roji
Copy link
Member

roji commented Mar 15, 2026

@AndriySvyryd I think this is more in your area, but definitely ping me if you want my eyes on something.

@JoasE JoasE requested a review from AndriySvyryd March 17, 2026 09:29
@AndriySvyryd AndriySvyryd merged commit 41d1ffd into dotnet:main Mar 17, 2026
10 checks passed
@AndriySvyryd
Copy link
Member

Thanks for your contribution!

@AndriySvyryd AndriySvyryd removed their assignment Mar 17, 2026
@roji roji linked an issue Mar 17, 2026 that may be closed by this pull request
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Cosmos support for complex types

4 participants