Skip to content

Commit

Permalink
Addressing API review feedback regarding json columns
Browse files Browse the repository at this point in the history
- renamed JsonColumnName to ContainerColumnName,
- renamed JsonColumnTypeMapping to ContainerColumnTypeMapping,
- changed RelationalModelValidator.ValidateJsonEntityProperties to protected method,
- moved JsonPropertyName methods on navigation into entity
  • Loading branch information
maumar committed Aug 12, 2022
1 parent 2dcd881 commit 1c7ef8c
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 235 deletions.
12 changes: 6 additions & 6 deletions src/EFCore.Relational/Design/AnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class AnnotationCodeGenerator : IAnnotationCodeGenerator
RelationalAnnotationNames.UpdateStoredProcedure,
RelationalAnnotationNames.MappingFragments,
RelationalAnnotationNames.RelationalOverrides,
RelationalAnnotationNames.JsonColumnTypeMapping
RelationalAnnotationNames.ContainerColumnTypeMapping
};

/// <summary>
Expand Down Expand Up @@ -200,17 +200,17 @@ public virtual IReadOnlyList<MethodCallCodeFragment> GenerateFluentApiCalls(
}
}

if (annotations.TryGetValue(RelationalAnnotationNames.JsonColumnName, out var jsonColumnNameAnnotation)
&& jsonColumnNameAnnotation != null && jsonColumnNameAnnotation.Value is string jsonColumnName
if (annotations.TryGetValue(RelationalAnnotationNames.ContainerColumnName, out var containerColumnNameAnnotation)
&& containerColumnNameAnnotation != null && containerColumnNameAnnotation.Value is string containerColumnName
&& entityType.IsOwned())
{
methodCallCodeFragments.Add(
new MethodCallCodeFragment(
nameof(RelationalOwnedNavigationBuilderExtensions.ToJson),
jsonColumnName));
containerColumnName));

annotations.Remove(RelationalAnnotationNames.JsonColumnName);
annotations.Remove(RelationalAnnotationNames.JsonColumnTypeMapping);
annotations.Remove(RelationalAnnotationNames.ContainerColumnName);
annotations.Remove(RelationalAnnotationNames.ContainerColumnTypeMapping);
}

methodCallCodeFragments.AddRange(GenerateFluentApiCallsHelper(entityType, annotations, GenerateFluentApi));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1146,4 +1146,43 @@ public static bool CanHaveTrigger(
tableName,
tableSchema,
fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention);

/// <summary>
/// Configures the entity mapped to a JSON column, mapping it to the given JSON property,
/// rather than using the navigation name leading to it.
/// </summary>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="name">JSON property name to be used.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>
/// The same builder instance if the configuration was applied,
/// <see langword="null" /> otherwise.
/// </returns>
public static IConventionEntityTypeBuilder? HasJsonPropertyName(
this IConventionEntityTypeBuilder entityTypeBuilder,
string? name,
bool fromDataAnnotation = false)
{
if (!entityTypeBuilder.CanSetJsonPropertyName(name, fromDataAnnotation))
{
return null;
}

entityTypeBuilder.Metadata.SetJsonPropertyName(name, fromDataAnnotation);

return entityTypeBuilder;
}

/// <summary>
/// Returns a value indicating whether the given value can be used as a JSON property name for the entity type.
/// </summary>
/// <param name="entityTypeBuilder">The builder for the entity type being configured.</param>
/// <param name="name">JSON property name to be used.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><see langword="true" /> if the given value can be set as JSON property name for this entity type.</returns>
public static bool CanSetJsonPropertyName(
this IConventionEntityTypeBuilder entityTypeBuilder,
string? name,
bool fromDataAnnotation = false)
=> entityTypeBuilder.CanSetAnnotation(RelationalAnnotationNames.JsonPropertyName, name, fromDataAnnotation);
}
131 changes: 90 additions & 41 deletions src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1847,87 +1847,136 @@ public static IEnumerable<ITrigger> GetDeclaredTriggers(this IEntityType entityT
/// <param name="entityType">The entity type.</param>
/// <returns>A value indicating whether the associated entity type is mapped to a JSON column.</returns>
public static bool IsMappedToJson(this IReadOnlyEntityType entityType)
=> !string.IsNullOrEmpty(entityType.GetJsonColumnName());
=> !string.IsNullOrEmpty(entityType.GetContainerColumnName());

/// <summary>
/// Sets the name of the JSON column to which the entity type is mapped.
/// Sets the name of the container column to which the entity type is mapped.
/// </summary>
/// <param name="entityType">The entity type to set the JSON column name for.</param>
/// <param name="entityType">The entity type to set the container column name for.</param>
/// <param name="columnName">The name to set.</param>
public static void SetJsonColumnName(this IMutableEntityType entityType, string? columnName)
=> entityType.SetOrRemoveAnnotation(RelationalAnnotationNames.JsonColumnName, columnName);
public static void SetContainerColumnName(this IMutableEntityType entityType, string? columnName)
=> entityType.SetOrRemoveAnnotation(RelationalAnnotationNames.ContainerColumnName, columnName);

/// <summary>
/// Sets the name of the JSON column to which the entity type is mapped.
/// Sets the name of the container column to which the entity type is mapped.
/// </summary>
/// <param name="entityType">The entity type to set the JSON column name for.</param>
/// <param name="entityType">The entity type to set the container column name for.</param>
/// <param name="columnName">The name to set.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static string? SetJsonColumnName(
public static string? SetContainerColumnName(
this IConventionEntityType entityType,
string? columnName,
bool fromDataAnnotation = false)
=> (string?)entityType.SetAnnotation(RelationalAnnotationNames.JsonColumnName, columnName, fromDataAnnotation)?.Value;
=> (string?)entityType.SetAnnotation(RelationalAnnotationNames.ContainerColumnName, columnName, fromDataAnnotation)?.Value;

/// <summary>
/// Gets the <see cref="ConfigurationSource" /> for the JSON column name.
/// Gets the <see cref="ConfigurationSource" /> for the container column name.
/// </summary>
/// <param name="entityType">The entity type to set the JSON column name for.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the JSON column name.</returns>
public static ConfigurationSource? GetJsonColumnNameConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.JsonColumnName)
/// <param name="entityType">The entity type to set the container column name for.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the container column name.</returns>
public static ConfigurationSource? GetContainerColumnNameConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.ContainerColumnName)
?.GetConfigurationSource();

/// <summary>
/// Gets the JSON column name to which the entity type is mapped.
/// Gets the container column name to which the entity type is mapped.
/// </summary>
/// <param name="entityType">The entity type to get the JSON column name for.</param>
/// <returns>The JSON column name to which the entity type is mapped.</returns>
public static string? GetJsonColumnName(this IReadOnlyEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.JsonColumnName)?.Value is string jsonColumnName
? jsonColumnName
: (entityType.FindOwnership()?.PrincipalEntityType.GetJsonColumnName());
/// <param name="entityType">The entity type to get the container column name for.</param>
/// <returns>The container column name to which the entity type is mapped.</returns>
public static string? GetContainerColumnName(this IReadOnlyEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.ContainerColumnName)?.Value is string columnName
? columnName
: (entityType.FindOwnership()?.PrincipalEntityType.GetContainerColumnName());

/// <summary>
/// Sets the type mapping for the JSON column to which the entity type is mapped.
/// Sets the type mapping for the container column to which the entity type is mapped.
/// </summary>
/// <param name="entityType">The entity type to set the JSON column type mapping for.</param>
/// <param name="entityType">The entity type to set the container column type mapping for.</param>
/// <param name="typeMapping">The type mapping to set.</param>
public static void SetJsonColumnTypeMapping(this IMutableEntityType entityType, RelationalTypeMapping typeMapping)
=> entityType.SetOrRemoveAnnotation(RelationalAnnotationNames.JsonColumnTypeMapping, typeMapping);
public static void SetContainerColumnTypeMapping(this IMutableEntityType entityType, RelationalTypeMapping typeMapping)
=> entityType.SetOrRemoveAnnotation(RelationalAnnotationNames.ContainerColumnTypeMapping, typeMapping);

/// <summary>
/// Sets the type mapping for the JSON column to which the entity type is mapped.
/// Sets the type mapping for the container column to which the entity type is mapped.
/// </summary>
/// <param name="entityType">The entity type to set the JSON column type mapping for.</param>
/// <param name="entityType">The entity type to set the container column type mapping for.</param>
/// <param name="typeMapping">The type mapping to set.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static RelationalTypeMapping? SetJsonColumnTypeMapping(
public static RelationalTypeMapping? SetContainerColumnTypeMapping(
this IConventionEntityType entityType,
RelationalTypeMapping? typeMapping,
bool fromDataAnnotation = false)
=> (RelationalTypeMapping?)entityType.SetAnnotation(RelationalAnnotationNames.JsonColumnTypeMapping, typeMapping, fromDataAnnotation)?.Value;
=> (RelationalTypeMapping?)entityType.SetAnnotation(RelationalAnnotationNames.ContainerColumnTypeMapping, typeMapping, fromDataAnnotation)?.Value;

/// <summary>
/// Gets the <see cref="ConfigurationSource" /> for the JSON column type mapping.
/// Gets the <see cref="ConfigurationSource" /> for the container column type mapping.
/// </summary>
/// <param name="entityType">The entity type to set the JSON column type mapping for.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the JSON column type mapping.</returns>
public static ConfigurationSource? GetJsonColumnTypeMappingConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.JsonColumnTypeMapping)
/// <param name="entityType">The entity type to set the container column type mapping for.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the container column type mapping.</returns>
public static ConfigurationSource? GetContainerColumnTypeMappingConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.ContainerColumnTypeMapping)
?.GetConfigurationSource();

/// <summary>
/// Gets the JSON column type mapping to which the entity type is mapped.
/// Gets the container column type mapping to which the entity type is mapped.
/// </summary>
/// <param name="entityType">The entity type to get the JSON column type mapping for.</param>
/// <returns>The JSON column type mapping to which the entity type is mapped.</returns>
public static RelationalTypeMapping? GetJsonColumnTypeMapping(this IReadOnlyEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.JsonColumnTypeMapping)?.Value is RelationalTypeMapping jsonColumnTypeMapping
? jsonColumnTypeMapping
: (entityType.FindOwnership()?.PrincipalEntityType.GetJsonColumnTypeMapping());
/// <param name="entityType">The entity type to get the container column type mapping for.</param>
/// <returns>The container column type mapping to which the entity type is mapped.</returns>
public static RelationalTypeMapping? GetContainerColumnTypeMapping(this IReadOnlyEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.ContainerColumnTypeMapping)?.Value is RelationalTypeMapping typeMapping
? typeMapping
: (entityType.FindOwnership()?.PrincipalEntityType.GetContainerColumnTypeMapping());

/// <summary>
/// Sets the value of JSON property name used for the given entity mapped to a JSON column.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="name">The name to be used.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>The configured value.</returns>
public static string? SetJsonPropertyName(
this IConventionEntityType entityType,
string? name,
bool fromDataAnnotation = false)
=> (string?)entityType.SetOrRemoveAnnotation(
RelationalAnnotationNames.JsonPropertyName,
Check.NullButNotEmpty(name, nameof(name)),
fromDataAnnotation)?.Value;

/// <summary>
/// Gets the value of JSON property name used for the given entity mapped to a JSON column.
/// </summary>
/// <remarks>
/// Unless configured explicitly, navigation name is used.
/// </remarks>
/// <param name="entityType">The entity type.</param>
/// <returns>
/// The value for the JSON property used to store this entity type.
/// <see langword="null" /> is returned for entities that are not mapped to a JSON column.
/// </returns>
public static string? GetJsonPropertyName(this IReadOnlyEntityType entityType)
=> (string?)entityType.FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.Value
?? (!entityType.IsMappedToJson() ? null : entityType.FindOwnership()!.GetNavigation(pointsToPrincipal: false)!.Name);

/// <summary>
/// Sets the value of JSON property name used for the given entity mapped to a JSON column.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="name">The name to be used.</param>
public static void SetJsonPropertyName(this IMutableEntityType entityType, string? name)
=> entityType.SetOrRemoveAnnotation(
RelationalAnnotationNames.JsonPropertyName,
Check.NullButNotEmpty(name, nameof(name)));

/// <summary>
/// Gets the <see cref="ConfigurationSource" /> for the JSON property name for a given entity Type.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns>The <see cref="ConfigurationSource" /> for the JSON property name for a given navigation.</returns>
public static ConfigurationSource? GetJsonPropertyNameConfigurationSource(this IConventionEntityType entityType)
=> entityType.FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.GetConfigurationSource();

#endregion
}

This file was deleted.

Loading

0 comments on commit 1c7ef8c

Please sign in to comment.