Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -199,6 +199,34 @@ protected override void ProcessEntityTypeAnnotations(
}
}

/// <summary>
/// Updates the complex type annotations that will be set on the read-only object.
/// </summary>
/// <param name="annotations">The annotations to be processed.</param>
/// <param name="complexType">The source complex type.</param>
/// <param name="runtimeComplexType">The target complex type that will contain the annotations.</param>
/// <param name="runtime">Indicates whether the given annotations are runtime annotations.</param>
protected override void ProcessComplexTypeAnnotations(
Dictionary<string, object?> annotations,
IComplexType complexType,
RuntimeComplexType runtimeComplexType,
bool runtime)
{
base.ProcessComplexTypeAnnotations(annotations, complexType, runtimeComplexType, runtime);

if (runtime)
{
annotations.Remove(RelationalAnnotationNames.TableMappings);
annotations.Remove(RelationalAnnotationNames.ViewMappings);
annotations.Remove(RelationalAnnotationNames.SqlQueryMappings);
annotations.Remove(RelationalAnnotationNames.FunctionMappings);
annotations.Remove(RelationalAnnotationNames.InsertStoredProcedureMappings);
annotations.Remove(RelationalAnnotationNames.DeleteStoredProcedureMappings);
annotations.Remove(RelationalAnnotationNames.UpdateStoredProcedureMappings);
annotations.Remove(RelationalAnnotationNames.DefaultMappings);
}
}

private static RuntimeEntityTypeMappingFragment Create(
IEntityTypeMappingFragment entityTypeMappingFragment,
RuntimeEntityType runtimeEntityType)
Expand Down
38 changes: 38 additions & 0 deletions src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,44 @@ public RelationalTypeMappingInfo(
DbType = dbType;
}

/// <summary>
/// Creates a new instance of <see cref="TypeMappingInfo" />.
/// </summary>
/// <param name="type">The CLR type in the model for which mapping is needed.</param>
/// <param name="typeMappingConfiguration">The type mapping configuration.</param>
/// <param name="elementTypeMapping">The type mapping for elements, if known.</param>
/// <param name="storeTypeName">The database type name.</param>
/// <param name="storeTypeNameBase">The provider-specific relational type name, with any facets removed.</param>
/// <param name="unicode">Specifies Unicode or ANSI mapping, or <see langword="null" /> for default.</param>
/// <param name="size">Specifies a size for the mapping, or <see langword="null" /> for default.</param>
/// <param name="precision">Specifies a precision for the mapping, or <see langword="null" /> for default.</param>
/// <param name="scale">Specifies a scale for the mapping, or <see langword="null" /> for default.</param>
public RelationalTypeMappingInfo(
Type type,
ITypeMappingConfiguration typeMappingConfiguration,
RelationalTypeMapping? elementTypeMapping = null,
string? storeTypeName = null,
string? storeTypeNameBase = null,
bool? unicode = null,
int? size = null,
int? precision = null,
int? scale = null)
{
_coreTypeMappingInfo = new TypeMappingInfo(
typeMappingConfiguration.GetValueConverter()?.ProviderClrType ?? type,
elementTypeMapping,
keyOrIndex: false,
unicode ?? typeMappingConfiguration.IsUnicode(),
size ?? typeMappingConfiguration.GetMaxLength(),
rowVersion: false,
precision ?? typeMappingConfiguration.GetPrecision(),
scale ?? typeMappingConfiguration.GetScale());

IsFixedLength = (bool?)typeMappingConfiguration[RelationalAnnotationNames.IsFixedLength];
StoreTypeName = storeTypeName;
StoreTypeNameBase = storeTypeNameBase;
}

/// <summary>
/// The core type mapping info.
/// </summary>
Expand Down
86 changes: 37 additions & 49 deletions src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,66 +343,34 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
{
type = type.UnwrapNullableType();
var typeConfiguration = model.FindTypeMappingConfiguration(type);
RelationalTypeMappingInfo mappingInfo;
Type? providerClrType = null;
ValueConverter? customConverter = null;
if (typeConfiguration == null)
if (typeConfiguration != null)
{
mappingInfo = new RelationalTypeMappingInfo(type, (RelationalTypeMapping?)elementMapping);
}
else
{
providerClrType = typeConfiguration.GetProviderClrType()?.UnwrapNullableType();
customConverter = typeConfiguration.GetValueConverter();

var isUnicode = typeConfiguration.IsUnicode();
var scale = typeConfiguration.GetScale();
var precision = typeConfiguration.GetPrecision();
var size = typeConfiguration.GetMaxLength();

bool? unicode = null;
int? scale = null;
int? precision = null;
int? size = null;
string? storeTypeNameBase = null;
var storeTypeName = (string?)typeConfiguration[RelationalAnnotationNames.ColumnType];
string? storeTypeBaseName = null;
if (storeTypeName != null)
{
storeTypeBaseName = ParseStoreTypeName(storeTypeName, ref isUnicode, ref size, ref precision, ref scale);
storeTypeNameBase = ParseStoreTypeName(storeTypeName, ref unicode, ref size, ref precision, ref scale);
}

var isFixedLength = (bool?)typeConfiguration[RelationalAnnotationNames.IsFixedLength];
mappingInfo = new RelationalTypeMappingInfo(
customConverter?.ProviderClrType ?? type,
(RelationalTypeMapping?)elementMapping,
storeTypeName,
storeTypeBaseName,
keyOrIndex: false,
unicode: isUnicode,
size: size,
rowVersion: false,
fixedLength: isFixedLength,
precision: precision,
scale: scale);
var mappingInfo = new RelationalTypeMappingInfo(type, typeConfiguration, (RelationalTypeMapping?)elementMapping,
storeTypeName, storeTypeNameBase, unicode, size, precision, scale);
var providerClrType = typeConfiguration.GetProviderClrType()?.UnwrapNullableType();
return FindMappingWithConversion(mappingInfo, providerClrType, customConverter: typeConfiguration.GetValueConverter());
}

return FindMappingWithConversion(mappingInfo, providerClrType, customConverter);
return FindMappingWithConversion(
new RelationalTypeMappingInfo(type, (RelationalTypeMapping?)elementMapping),
providerClrType: null,
customConverter: null);
}

/// <summary>
/// Finds the type mapping for a given <see cref="MemberInfo" /> representing
/// a field or a property of a CLR type.
/// </summary>
/// <remarks>
/// <para>
/// Note: Only call this method if there is no <see cref="IProperty" /> available, otherwise
/// call <see cref="FindMapping(IProperty)" />
/// </para>
/// <para>
/// Note: providers should typically not need to override this method.
/// </para>
/// </remarks>
/// <param name="member">The field or property.</param>
/// <returns>The type mapping, or <see langword="null" /> if none was found.</returns>
/// <inheritdoc/>
public override RelationalTypeMapping? FindMapping(MemberInfo member)
{
// TODO: Remove this, see #11124
if (member.GetCustomAttribute<ColumnAttribute>(true) is ColumnAttribute attribute)
{
var storeTypeName = attribute.TypeName;
Expand All @@ -417,7 +385,27 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
new RelationalTypeMappingInfo(member, null, storeTypeName, storeTypeNameBase, unicode, size, precision, scale), null);
}

return FindMappingWithConversion(new RelationalTypeMappingInfo(member), null);
return FindMappingWithConversion(new RelationalTypeMappingInfo(member), null, null);
}

/// <inheritdoc/>
public override RelationalTypeMapping? FindMapping(MemberInfo member, IModel model, bool useAttributes)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Might providers need to react to this? @roji @lauxjpn

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't override any of these FindMapping overloads (which accept MemberInfo) in Npgsql, only the version which accepts RelationalTypeMappingInfo... That should be OK, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep

{
if (useAttributes
&& member.GetCustomAttribute<ColumnAttribute>(true) is ColumnAttribute attribute)
{
var storeTypeName = attribute.TypeName;
bool? unicode = null;
int? size = null;
int? precision = null;
int? scale = null;
var storeTypeNameBase = ParseStoreTypeName(storeTypeName, ref unicode, ref size, ref precision, ref scale);

return FindMappingWithConversion(
new RelationalTypeMappingInfo(member, null, storeTypeName, storeTypeNameBase, unicode, size, precision, scale), null);
}

return FindMappingWithConversion(new RelationalTypeMappingInfo(member), null, null);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ public interface ICSharpRuntimeAnnotationCodeGenerator
/// <summary>
/// Generates code to create the given annotations.
/// </summary>
/// <param name="complexProperty">The entity type to which the annotations are applied.</param>
/// <param name="complexProperty">The complex property to which the annotations are applied.</param>
/// <param name="parameters">Additional parameters used during code generation.</param>
void Generate(IComplexProperty complexProperty, CSharpRuntimeAnnotationCodeGeneratorParameters parameters);

/// <summary>
/// Generates code to create the given annotations.
/// </summary>
/// <param name="complexType">The entity type to which the annotations are applied.</param>
/// <param name="complexType">The complex type to which the annotations are applied.</param>
/// <param name="parameters">Additional parameters used during code generation.</param>
void Generate(IComplexType complexType, CSharpRuntimeAnnotationCodeGeneratorParameters parameters);

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Infrastructure/ModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ void Validate(IConventionTypeBase typeBase)
}

var targetType = Dependencies.MemberClassifier.FindCandidateNavigationPropertyType(
clrProperty, conventionModel, out var targetOwned);
clrProperty, conventionModel, useAttributes: true, out var targetOwned);
if (targetType == null
&& clrProperty.FindSetterProperty() == null)
{
Expand Down
2 changes: 2 additions & 0 deletions src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ bool CanSetProviderValueComparer(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
IConventionElementTypeBuilder? SetElementType(Type? elementType, bool fromDataAnnotation = false);

/// <summary>
Expand All @@ -564,5 +565,6 @@ bool CanSetProviderValueComparer(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
bool CanSetElementType(Type? elementType, bool fromDataAnnotation = false);
}
Loading