-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Metadata for primitive collection mapping
Part of #30730 Some stuff remaining, but wanted to get this out there for initial review. Missing: - ElementType in compiled model - Negative cases - More tests
- Loading branch information
1 parent
f9d827d
commit 207a3ac
Showing
51 changed files
with
4,729 additions
and
532 deletions.
There are no files selected for viewing
131 changes: 131 additions & 0 deletions
131
src/EFCore.Relational/Extensions/RelationalElementTypeBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// 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> | ||
/// Relational database specific extension methods for <see cref="ElementTypeBuilder" />. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
public static class RelationalElementTypeBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Configures the data type of the elements of the collection. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
/// <param name="elementTypeBuilder">The builder for the elements being configured.</param> | ||
/// <param name="typeName">The name of the data type of the elements.</param> | ||
/// <returns>The same builder instance so that multiple calls can be chained.</returns> | ||
public static ElementTypeBuilder ElementsHaveDatabaseType( | ||
this ElementTypeBuilder elementTypeBuilder, | ||
string? typeName) | ||
{ | ||
Check.NullButNotEmpty(typeName, nameof(typeName)); | ||
|
||
elementTypeBuilder.Metadata.SetStoreType(typeName); | ||
|
||
return elementTypeBuilder; | ||
} | ||
|
||
/// <summary> | ||
/// Configures the data type of the elements of the collection. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
/// <param name="elementTypeBuilder"> builder for the elements being configured.</param> | ||
/// <param name="typeName">The name of the data type of the elements.</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 IConventionElementTypeBuilder? ElementsHaveDatabaseType( | ||
this IConventionElementTypeBuilder elementTypeBuilder, | ||
string? typeName, | ||
bool fromDataAnnotation = false) | ||
{ | ||
if (!elementTypeBuilder.CanSetDatabaseType(typeName, fromDataAnnotation)) | ||
{ | ||
return null; | ||
} | ||
|
||
elementTypeBuilder.Metadata.SetStoreType(typeName, fromDataAnnotation); | ||
return elementTypeBuilder; | ||
} | ||
|
||
/// <summary> | ||
/// Returns a value indicating whether the given data type can be set for the elements. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
/// <param name="elementTypeBuilder"> builder for the elements being configured.</param> | ||
/// <param name="typeName">The name of the data type of the elements.</param> | ||
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param> | ||
/// <returns><see langword="true" /> if the given data type can be set for the property.</returns> | ||
public static bool CanSetDatabaseType( | ||
this IConventionElementTypeBuilder elementTypeBuilder, | ||
string? typeName, | ||
bool fromDataAnnotation = false) | ||
=> elementTypeBuilder.CanSetAnnotation(RelationalAnnotationNames.StoreType, typeName, fromDataAnnotation); | ||
|
||
/// <summary> | ||
/// Configures the elements as capable of storing only fixed-length data, such as strings. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
/// <param name="elementTypeBuilder">The builder for the elements being configured.</param> | ||
/// <param name="fixedLength">A value indicating whether the elements are constrained to fixed length values.</param> | ||
/// <returns>The same builder instance so that multiple configuration calls can be chained.</returns> | ||
public static ElementTypeBuilder ElementsAreFixedLength( | ||
this ElementTypeBuilder elementTypeBuilder, | ||
bool fixedLength = true) | ||
{ | ||
elementTypeBuilder.Metadata.SetIsFixedLength(fixedLength); | ||
|
||
return elementTypeBuilder; | ||
} | ||
|
||
/// <summary> | ||
/// Configures the elements as capable of storing only fixed-length data, such as strings. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
/// <param name="elementTypeBuilder"> builder for the elements being configured.</param> | ||
/// <param name="fixedLength">A value indicating whether the elements are constrained to fixed length values.</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 IConventionElementTypeBuilder? ElementsAreFixedLength( | ||
this IConventionElementTypeBuilder elementTypeBuilder, | ||
bool? fixedLength, | ||
bool fromDataAnnotation = false) | ||
{ | ||
if (!elementTypeBuilder.CanSetFixedLength(fixedLength, fromDataAnnotation)) | ||
{ | ||
return null; | ||
} | ||
|
||
elementTypeBuilder.Metadata.SetIsFixedLength(fixedLength, fromDataAnnotation); | ||
return elementTypeBuilder; | ||
} | ||
|
||
/// <summary> | ||
/// Returns a value indicating whether the elements can be configured as being fixed length or not. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
/// <param name="elementTypeBuilder"> builder for the elements being configured.</param> | ||
/// <param name="fixedLength">A value indicating whether the elements are constrained to fixed length values.</param> | ||
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param> | ||
/// <returns><see langword="true" /> if the elements can be configured as being fixed length or not.</returns> | ||
public static bool CanSetFixedLength( | ||
this IConventionElementTypeBuilder elementTypeBuilder, | ||
bool? fixedLength, | ||
bool fromDataAnnotation = false) | ||
=> elementTypeBuilder.CanSetAnnotation(RelationalAnnotationNames.IsFixedLength, fixedLength, fromDataAnnotation); | ||
} |
143 changes: 143 additions & 0 deletions
143
src/EFCore.Relational/Extensions/RelationalElementTypeExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// 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> | ||
/// <see cref="IElementType" /> extension methods for relational database metadata. | ||
/// </summary> | ||
/// <remarks> | ||
/// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. | ||
/// </remarks> | ||
public static class RelationalElementTypeExtensions | ||
{ | ||
/// <summary> | ||
/// Returns the database type of the elements, or <see langword="null" /> if the database type could not be found. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns> | ||
/// The database type of the elements, or <see langword="null" /> if the database type could not be found. | ||
/// </returns> | ||
public static string? GetStoreType(this IReadOnlyElementType elementType) | ||
=> (string?)(elementType.FindRelationalTypeMapping()?.StoreType | ||
?? elementType.FindAnnotation(RelationalAnnotationNames.StoreType)?.Value); | ||
|
||
/// <summary> | ||
/// Returns the database type of the elements. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>The database type of the elements.</returns> | ||
public static string GetStoreType(this IElementType elementType) | ||
=> ((IReadOnlyElementType)elementType).GetStoreType()!; | ||
|
||
/// <summary> | ||
/// Sets the database type of the elements. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <param name="value">The value to set.</param> | ||
public static void SetStoreType(this IMutableElementType elementType, string? value) | ||
=> elementType.SetOrRemoveAnnotation( | ||
RelationalAnnotationNames.StoreType, | ||
Check.NullButNotEmpty(value, nameof(value))); | ||
|
||
/// <summary> | ||
/// Sets the database type of the elements. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <param name="value">The value 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? SetStoreType( | ||
this IConventionElementType elementType, | ||
string? value, | ||
bool fromDataAnnotation = false) | ||
=> (string?)elementType.SetOrRemoveAnnotation( | ||
RelationalAnnotationNames.StoreType, | ||
Check.NullButNotEmpty(value, nameof(value)), | ||
fromDataAnnotation)?.Value; | ||
|
||
/// <summary> | ||
/// Gets the <see cref="ConfigurationSource" /> for the database type. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>The <see cref="ConfigurationSource" /> for the column name.</returns> | ||
public static ConfigurationSource? GetStoreTypeConfigurationSource(this IConventionElementType elementType) | ||
=> elementType.FindAnnotation(RelationalAnnotationNames.StoreType)?.GetConfigurationSource(); | ||
|
||
/// <summary> | ||
/// Returns a flag indicating whether the elements are capable of storing only fixed-length data, such as strings. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>A flag indicating whether the elements arecapable of storing only fixed-length data, such as strings.</returns> | ||
public static bool? IsFixedLength(this IReadOnlyElementType elementType) | ||
=> (bool?)elementType.FindAnnotation(RelationalAnnotationNames.IsFixedLength)?.Value; | ||
|
||
/// <summary> | ||
/// Returns a flag indicating whether the elements are capable of storing only fixed-length data, such as strings. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <param name="storeObject">The identifier of the table-like store object containing the column.</param> | ||
/// <returns>A flag indicating whether the elements are capable of storing only fixed-length data, such as strings.</returns> | ||
public static bool? IsFixedLength(this IReadOnlyElementType elementType, in StoreObjectIdentifier storeObject) | ||
=> (bool?)elementType.FindAnnotation(RelationalAnnotationNames.IsFixedLength)?.Value; | ||
|
||
/// <summary> | ||
/// Sets a flag indicating whether the elements are capable of storing only fixed-length data, such as strings. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <param name="fixedLength">A value indicating whether the elements are constrained to fixed length values.</param> | ||
public static void SetIsFixedLength(this IMutableElementType elementType, bool? fixedLength) | ||
=> elementType.SetOrRemoveAnnotation(RelationalAnnotationNames.IsFixedLength, fixedLength); | ||
|
||
/// <summary> | ||
/// Sets a flag indicating whether the elements are capable of storing only fixed-length data, such as strings. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <param name="fixedLength">A value indicating whether the element are constrained to fixed length values.</param> | ||
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param> | ||
/// <returns>The configured value.</returns> | ||
public static bool? SetIsFixedLength( | ||
this IConventionElementType elementType, | ||
bool? fixedLength, | ||
bool fromDataAnnotation = false) | ||
=> (bool?)elementType.SetOrRemoveAnnotation( | ||
RelationalAnnotationNames.IsFixedLength, | ||
fixedLength, | ||
fromDataAnnotation)?.Value; | ||
|
||
/// <summary> | ||
/// Gets the <see cref="ConfigurationSource" /> for <see cref="IsFixedLength(IReadOnlyElementType)" />. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>The <see cref="ConfigurationSource" /> for <see cref="IsFixedLength(IReadOnlyElementType)" />.</returns> | ||
public static ConfigurationSource? GetIsFixedLengthConfigurationSource(this IConventionElementType elementType) | ||
=> elementType.FindAnnotation(RelationalAnnotationNames.IsFixedLength)?.GetConfigurationSource(); | ||
|
||
/// <summary> | ||
/// Returns the collation to be used for the column. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>The collation for the column this element is mapped to.</returns> | ||
public static string? GetCollation(this IReadOnlyElementType elementType) | ||
=> (elementType is RuntimeElementType) | ||
? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData) | ||
: (string?)elementType.FindAnnotation(RelationalAnnotationNames.Collation)?.Value; | ||
|
||
/// <summary> | ||
/// Returns the <see cref="RelationalTypeMapping" /> for the given element on a finalized model. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>The type mapping.</returns> | ||
[DebuggerStepThrough] | ||
public static RelationalTypeMapping GetRelationalTypeMapping(this IReadOnlyElementType elementType) | ||
=> (RelationalTypeMapping)elementType.GetTypeMapping(); | ||
|
||
/// <summary> | ||
/// Returns the <see cref="RelationalTypeMapping" /> for the given element on a finalized model. | ||
/// </summary> | ||
/// <param name="elementType">The element.</param> | ||
/// <returns>The type mapping, or <see langword="null" /> if none was found.</returns> | ||
[DebuggerStepThrough] | ||
public static RelationalTypeMapping? FindRelationalTypeMapping(this IReadOnlyElementType elementType) | ||
=> (RelationalTypeMapping?)elementType.FindTypeMapping(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.