Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Cosmos-specific extension methods for <see cref="ComplexCollectionBuilder" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosComplexCollectionBuilderExtensions
{
/// <summary>
/// Configures the property name that the complex collection is mapped to when stored as an embedded document.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <param name="complexPropertyBuilder">The builder for the complex type being configured.</param>
/// <param name="name">The name of the parent property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexCollectionBuilder ToJsonProperty(
this ComplexCollectionBuilder complexPropertyBuilder,
string? name)
{
complexPropertyBuilder.Metadata.SetJsonPropertyName(name);
return complexPropertyBuilder;
}

/// <summary>
/// Configures the property name that the the complex collection is mapped to when stored as an embedded document.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <param name="complexPropertyBuilder">The builder for the complex type being configured.</param>
/// <param name="name">The name of the parent property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexCollectionBuilder<TComplex> ToJsonProperty<TComplex>(
this ComplexCollectionBuilder<TComplex> complexPropertyBuilder,
string? name)
where TComplex : notnull
{
complexPropertyBuilder.Metadata.SetJsonPropertyName(name);
return complexPropertyBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// ReSharper disable once CheckNamespace

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Cosmos-specific extension methods for <see cref="ComplexCollectionTypePropertyBuilder" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosComplexCollectionTypePropertyBuilderExtensions
{
/// <summary>
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
/// </summary>
/// <remarks>
/// <para>
/// If an empty string is supplied, the property will not be persisted.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </para>
/// </remarks>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexCollectionTypePropertyBuilder ToJsonProperty(
this ComplexCollectionTypePropertyBuilder propertyBuilder,
string name)
{
Check.NotEmpty(name);

propertyBuilder.Metadata.SetJsonPropertyName(name);

return propertyBuilder;
}

/// <summary>
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <typeparam name="TProperty">The type of the property being configured.</typeparam>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexCollectionTypePropertyBuilder<TProperty> ToJsonProperty<TProperty>(
this ComplexCollectionTypePropertyBuilder<TProperty> propertyBuilder,
string name)
=> (ComplexCollectionTypePropertyBuilder<TProperty>)ToJsonProperty((ComplexCollectionTypePropertyBuilder)propertyBuilder, name);

// Vector and fulltext properties are not supported on collection types
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Cosmos-specific extension methods for <see cref="ComplexPropertyBuilder" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosComplexPropertyBuilderExtensions
{
/// <summary>
/// Configures the property name that the complex property is mapped to when stored as an embedded document.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <param name="complexPropertyBuilder">The builder for the complex type being configured.</param>
/// <param name="name">The name of the parent property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexPropertyBuilder ToJsonProperty(
this ComplexPropertyBuilder complexPropertyBuilder,
string? name)
{
complexPropertyBuilder.Metadata.SetJsonPropertyName(name);
return complexPropertyBuilder;
}

/// <summary>
/// Configures the property name that the complex property is mapped to when stored as an embedded document.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <param name="complexPropertyBuilder">The builder for the complex type being configured.</param>
/// <param name="name">The name of the parent property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexPropertyBuilder<TComplex> ToJsonProperty<TComplex>(
this ComplexPropertyBuilder<TComplex> complexPropertyBuilder,
string? name)
where TComplex : notnull
{
complexPropertyBuilder.Metadata.SetJsonPropertyName(name);
return complexPropertyBuilder;
}
}
35 changes: 35 additions & 0 deletions src/EFCore.Cosmos/Extensions/CosmosComplexPropertyExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Complex property extension methods for Cosmos metadata.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosComplexPropertyExtensions
{
/// <summary>
/// Returns the property name that the property is mapped to when targeting Cosmos.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>Returns the property name that the property is mapped to when targeting Cosmos.</returns>
public static string GetJsonPropertyName(this IReadOnlyComplexProperty property)
=> (string?)property[CosmosAnnotationNames.PropertyName]
?? property.Name;

/// <summary>
/// Sets the property name that the property is mapped to when targeting Cosmos.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="name">The name to set.</param>
public static void SetJsonPropertyName(this IMutableComplexProperty property, string? name)
=> property.SetOrRemoveAnnotation(
CosmosAnnotationNames.PropertyName,
Check.NullButNotEmpty(name));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Cosmos-specific extension methods for <see cref="ComplexTypePrimitiveCollectionBuilder" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosComplexTypePrimitiveCollectionBuilderExtensions
{
/// <summary>
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
/// </summary>
/// <remarks>
/// <para>
/// If an empty string is supplied, the property will not be persisted.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </para>
/// </remarks>
/// <param name="primitiveCollectionBuilder">The builder for the property being configured.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexTypePrimitiveCollectionBuilder ToJsonProperty(
this ComplexTypePrimitiveCollectionBuilder primitiveCollectionBuilder,
string name)
{
Check.NotNull(name);

primitiveCollectionBuilder.Metadata.SetJsonPropertyName(name);

return primitiveCollectionBuilder;
}

/// <summary>
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <typeparam name="TProperty">The type of the property being configured.</typeparam>
/// <param name="primitiveCollectionBuilder">The builder for the property being configured.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexTypePrimitiveCollectionBuilder<TProperty> ToJsonProperty<TProperty>(
this ComplexTypePrimitiveCollectionBuilder<TProperty> primitiveCollectionBuilder,
string name)
=> (ComplexTypePrimitiveCollectionBuilder<TProperty>)ToJsonProperty((ComplexTypePrimitiveCollectionBuilder)primitiveCollectionBuilder, name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// ReSharper disable once CheckNamespace

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Cosmos-specific extension methods for <see cref="ComplexTypePropertyBuilder" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosComplexTypePropertyBuilderExtensions
{
/// <summary>
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
/// </summary>
/// <remarks>
/// <para>
/// If an empty string is supplied, the property will not be persisted.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </para>
/// </remarks>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexTypePropertyBuilder ToJsonProperty(
this ComplexTypePropertyBuilder propertyBuilder,
string name)
{
Check.NotNull(name);

propertyBuilder.Metadata.SetJsonPropertyName(name);

return propertyBuilder;
}

/// <summary>
/// Configures the property name that the property is mapped to when targeting Azure Cosmos.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
/// <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
/// <typeparam name="TProperty">The type of the property being configured.</typeparam>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="name">The name of the property.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
public static ComplexTypePropertyBuilder<TProperty> ToJsonProperty<TProperty>(
this ComplexTypePropertyBuilder<TProperty> propertyBuilder,
string name)
=> (ComplexTypePropertyBuilder<TProperty>)ToJsonProperty((ComplexTypePropertyBuilder)propertyBuilder, name);

// Vector and fulltext properties are not supported on complex types, because you can't define indexes on complex types
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public static JToken SerializeObjectToComplexProperty(IComplexType type, object?
{
var jsonPropertyName = property.GetJsonPropertyName();

if (string.IsNullOrEmpty(jsonPropertyName))
{
continue;
}

var propertyValue = property.GetGetter().GetClrValue(value);
#pragma warning disable EF1001 // Internal EF Core API usage.
var providerValue = property.ConvertToProviderValue(propertyValue);
Expand All @@ -77,7 +82,7 @@ public static JToken SerializeObjectToComplexProperty(IComplexType type, object?

foreach (var complexProperty in type.GetComplexProperties())
{
var jsonPropertyName = complexProperty.Name;
var jsonPropertyName = complexProperty.GetJsonPropertyName();
var propertyValue = complexProperty.GetGetter().GetClrValue(value);
if (propertyValue is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ private BlockExpression CreateComplexPropertyAssignmentBlock(MemberExpression me
Call(
CosmosProjectionBindingRemovingExpressionVisitorBase.ToObjectWithSerializerMethodInfo.MakeGenericMethod(typeof(JObject)),
Call(_parentJObject, CosmosProjectionBindingRemovingExpressionVisitorBase.GetItemMethodInfo,
Constant(complexProperty.Name))));
Constant(complexProperty.GetJsonPropertyName()))));

var materializeExpression = CreateComplexTypeMaterializeExpression(complexProperty, jObjectVariable);
if (complexProperty.IsNullable)
Expand Down Expand Up @@ -227,7 +227,7 @@ private BlockExpression CreateComplexCollectionAssignmentBlock(MemberExpression
Call(
CosmosProjectionBindingRemovingExpressionVisitorBase.ToObjectWithSerializerMethodInfo.MakeGenericMethod(typeof(JArray)),
Call(_parentJObject, CosmosProjectionBindingRemovingExpressionVisitorBase.GetItemMethodInfo,
Constant(complexProperty.Name))));
Constant(complexProperty.GetJsonPropertyName()))));

var jObjectParameter = Parameter(typeof(JObject), "complexJObject" + _currentComplexIndex);
var materializeExpression = CreateComplexTypeMaterializeExpression(complexProperty, jObjectParameter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.Cosmos.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
Expand Down Expand Up @@ -42,7 +41,7 @@ public ObjectAccessExpression(
break;
case IComplexProperty complexProperty:
structuralType = complexProperty.ComplexType;
propertyName = complexProperty.Name;
propertyName = complexProperty.GetJsonPropertyName();
break;
default:
throw new UnreachableException($"Unexpected structural property type: {structuralProperty.GetType().FullName}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.Cosmos.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
Expand Down Expand Up @@ -44,7 +43,7 @@ public ObjectArrayAccessExpression(
break;
case IComplexProperty complexProperty:
targetType = complexProperty.ComplexType;
propertyName = complexProperty.Name;
propertyName = complexProperty.GetJsonPropertyName();;
break;
default:
throw new UnreachableException($"Unexpected structural property type: {structuralProperty.GetType().FullName}");
Expand Down
Loading
Loading