Skip to content

Commit

Permalink
Be explicit about type mappings being available on the finalized model
Browse files Browse the repository at this point in the history
Part of #15663
Fixes #14433

The `GetTypeMapping` and `GetRelationalTypeMapping` methods will throw if there isn't a type mapping annotated on the model. Model finalization ensures that this is true.

Find methods still exist for cases where they need to be called before the model is finalized, and also so as not to break when not needed. However, see #16177
  • Loading branch information
ajcvickers committed Jun 20, 2019
1 parent 823ca6b commit dfe3110
Show file tree
Hide file tree
Showing 57 changed files with 1,678 additions and 1,767 deletions.
4 changes: 2 additions & 2 deletions src/EFCore.Cosmos/Query/Internal/ValueBufferFactoryFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private static Expression CreateGetValueExpression(
var storeName = property.GetCosmosPropertyName();
if (storeName.Length == 0)
{
var type = property.FindMapping()?.Converter?.ProviderClrType
var type = property.GetTypeMapping().Converter?.ProviderClrType
?? property.ClrType;

Expression calculatedExpression = Expression.Default(type);
Expand All @@ -80,7 +80,7 @@ public static Expression CreateGetStoreValueExpression(Expression jObjectExpress
Expression.Constant(storeName));

var modelClrType = property.ClrType;
var converter = property.FindMapping().Converter;
var converter = property.GetTypeMapping().Converter;
if (converter != null)
{
var nullableExpression = valueExpression;
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Cosmos/Update/Internal/DocumentSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private static JToken ConvertPropertyValue(IProperty property, object value)
return null;
}

var converter = property.FindMapping().Converter;
var converter = property.GetTypeMapping().Converter;
if (converter != null)
{
value = converter.ConvertToProvider(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,7 @@ protected virtual void GeneratePropertyAnnotations([NotNull] IProperty property,
}

private static ValueConverter FindValueConverter(IProperty property)
=> property.FindMapping()?.Converter
?? property.GetValueConverter();
=> property.GetTypeMapping().Converter;

/// <summary>
/// Generates code for <see cref="IKey" /> objects.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ private static IEnumerable<IAnnotatable> GetAnnotatables(IEnumerable<MigrationOp
protected virtual IEnumerable<string> GetNamespaces([NotNull] IModel model)
=> model.GetEntityTypes().SelectMany(
e => e.GetDeclaredProperties()
.SelectMany(p => (p.FindMapping()?.Converter?.ProviderClrType ?? p.ClrType).GetNamespaces()))
.SelectMany(p => (p.GetTypeMapping().Converter?.ProviderClrType ?? p.ClrType).GetNamespaces()))
.Concat(GetAnnotationNamespaces(GetAnnotatables(model)));

private static IEnumerable<IAnnotatable> GetAnnotatables(IModel model)
Expand Down Expand Up @@ -264,7 +264,7 @@ private static IEnumerable<string> GetAnnotationNamespaces(IEnumerable<IAnnotata
private static Type GetProviderType(IAnnotatable annotatable, Type valueType)
=> annotatable is IProperty property
&& valueType.UnwrapNullableType() == property.ClrType.UnwrapNullableType()
? property.FindMapping()?.Converter?.ProviderClrType ?? valueType
? property.GetTypeMapping().Converter?.ProviderClrType ?? valueType
: valueType;
}
}
2 changes: 1 addition & 1 deletion src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private static List<ValueComparer> GetStructuralComparers(IEnumerable<IProperty>
=> properties.Select(GetStructuralComparer).ToList();

private static ValueComparer GetStructuralComparer(IProperty p)
=> p.GetStructuralValueComparer() ?? p.FindMapping()?.StructuralComparer;
=> p.GetStructuralValueComparer() ?? p.GetTypeMapping().StructuralComparer;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public override ValueGenerator Select(IProperty property, IEntityType entityType

return property.GetValueGeneratorFactory() == null
&& property.ClrType.IsInteger()
&& property.ClrType.UnwrapNullableType() != typeof(char)
? GetOrCreate(property)
: base.Select(property, entityType);
}
Expand Down
13 changes: 11 additions & 2 deletions src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,13 +397,22 @@ public static void SetIsFixedLength([NotNull] this IConventionProperty property,
=> property.FindAnnotation(RelationalAnnotationNames.IsFixedLength)?.GetConfigurationSource();

/// <summary>
/// Returns the <see cref="RelationalTypeMapping" /> for the given property.
/// Returns the <see cref="RelationalTypeMapping" /> for the given property on a finalized model.
/// </summary>
/// <param name="property"> The property. </param>
/// <returns> The type mapping. </returns>
[DebuggerStepThrough]
public static RelationalTypeMapping GetRelationalTypeMapping([NotNull] this IProperty property)
=> (RelationalTypeMapping)property.GetTypeMapping();

/// <summary>
/// Returns the <see cref="RelationalTypeMapping" /> for the given property on a finalized model.
/// </summary>
/// <param name="property"> The property. </param>
/// <returns> The type mapping, or null if none was found. </returns>
[DebuggerStepThrough]
public static RelationalTypeMapping FindRelationalMapping([NotNull] this IProperty property)
=> property[CoreAnnotationNames.TypeMapping] as RelationalTypeMapping;
=> (RelationalTypeMapping)property.FindMapping();

/// <summary>
/// <para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,9 @@ protected virtual void ValidateSharedColumnsCompatibility(
}

var currentTypeString = property.GetColumnType()
?? property.FindRelationalMapping()?.StoreType;
?? property.GetRelationalTypeMapping().StoreType;
var previousTypeString = duplicateProperty.GetColumnType()
?? duplicateProperty.FindRelationalMapping()?.StoreType;
?? duplicateProperty.GetRelationalTypeMapping().StoreType;
if (!string.Equals(currentTypeString, previousTypeString, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public virtual void ProcessPropertyAnnotationChanged(
/// <param name="property"> The property. </param>
/// <returns> The store value generation strategy to set for the given property. </returns>
protected override ValueGenerated? GetValueGenerated(IConventionProperty property)
=> GetValueGenerated((IProperty)property);
=> GetValueGenerated(property);

/// <summary>
/// Returns the store value generation strategy to set for the given property.
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Relational/Migrations/HistoryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private IModel EnsureModel()
x.ToTable(TableName, TableSchema);
});

_model = modelBuilder.Model;
_model = modelBuilder.FinalizeModel();
}

return _model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1788,8 +1788,8 @@ protected virtual void DiffData(
var targetValue = entry.GetCurrentValue(targetProperty);
var comparer = targetProperty.GetValueComparer() ??
sourceProperty.GetValueComparer() ??
targetProperty.FindMapping()?.Comparer ??
sourceProperty.FindMapping()?.Comparer;
targetProperty.GetTypeMapping().Comparer ??
sourceProperty.GetTypeMapping().Comparer;

var modelValuesChanged
= sourceProperty.ClrType.UnwrapNullableType() == targetProperty.ClrType.UnwrapNullableType()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
return CreateGetValueExpression(
projectionIndex,
IsNullableProjection(projection),
property.FindRelationalMapping(),
property.GetRelationalTypeMapping(),
methodCallExpression.Type);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions
public class ColumnExpression : SqlExpression
{
internal ColumnExpression(IProperty property, TableExpressionBase table, bool nullable)
: this(property.GetColumnName(), table, property.ClrType, property.FindRelationalMapping(),
: this(property.GetColumnName(), table, property.ClrType, property.GetRelationalTypeMapping(),
nullable || property.IsNullable || property.DeclaringEntityType.BaseType != null)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public static IRelationalCommandBuilder AddParameter(
new TypeMappedRelationalParameter(
invariantName,
name,
property.FindRelationalMapping(),
property.GetRelationalTypeMapping(),
property.IsNullable));
}

Expand Down Expand Up @@ -277,7 +277,7 @@ public static IRelationalCommandBuilder AddPropertyParameter(
new TypeMappedPropertyRelationalParameter(
invariantName,
name,
property.FindRelationalMapping(),
property.GetRelationalTypeMapping(),
property));
}

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Relational/Storage/TypeMaterializationInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public TypeMaterializationInfo(

if (mapping == null)
{
mapping = property?.FindRelationalMapping()
mapping = property?.GetRelationalTypeMapping()
?? typeMappingSource?.GetMapping(modelClrType);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public override IEnumerable<IAnnotation> For(IProperty property)
}

private static bool HasConverter(IProperty property)
=> (property.FindMapping()?.Converter
?? property.GetValueConverter()) != null;
=> property.GetTypeMapping().Converter != null;
}
}
4 changes: 2 additions & 2 deletions src/EFCore/ChangeTracking/Internal/ChangeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ private void LocalDetectChanges(InternalEntityEntry entry)
var current = entry[property];
var original = entry.GetOriginalValue(property);

var comparer = property.GetValueComparer() ?? property.FindMapping()?.Comparer;
var comparer = property.GetValueComparer() ?? property.GetTypeMapping().Comparer;

if (comparer == null)
{
Expand Down Expand Up @@ -253,7 +253,7 @@ private void DetectKeyChange(InternalEntityEntry entry, IProperty property)
var currentValue = entry[property];

var comparer = property.GetKeyValueComparer()
?? property.FindMapping()?.KeyComparer;
?? property.GetTypeMapping().KeyComparer;

// Note that mutation of a byte[] key is not supported or detected, but two different instances
// of byte[] with the same content must be detected as equal.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ protected virtual bool TryCreateFromEntry(
/// </summary>
protected static IEqualityComparer<object[]> CreateEqualityComparer([NotNull] IReadOnlyList<IProperty> properties)
{
var comparers = properties.Select(p => p.GetKeyValueComparer() ?? p.FindMapping()?.KeyComparer).ToList();
var comparers = properties.Select(p => p.GetKeyValueComparer() ?? p.GetTypeMapping().KeyComparer).ToList();

return comparers.All(c => c != null)
? new CompositeCustomComparer(comparers)
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ private void SetProperty(
private static Func<object, object, bool> ValuesEqualFunc(IProperty property)
{
var comparer = property.GetValueComparer()
?? property.FindMapping()?.Comparer;
?? property.GetTypeMapping().Comparer;

return comparer != null
? (Func<object, object, bool>)((l, r) => comparer.Equals(l, r))
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/NavigationFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ private static bool PrincipalValueEqualsDependentValue(
object dependentValue,
object principalValue)
=> (principalProperty.GetKeyValueComparer()
?? principalProperty.FindMapping()?.KeyComparer)
?? principalProperty.GetTypeMapping().KeyComparer)
?.Equals(dependentValue, principalValue)
?? StructuralComparisons.StructuralEqualityComparer.Equals(
dependentValue,
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/OriginalValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void AcceptChanges(InternalEntityEntry entry)

private static object SnapshotValue(IProperty property, object value)
{
var comparer = property.GetValueComparer() ?? property.FindMapping()?.Comparer;
var comparer = property.GetValueComparer() ?? property.GetTypeMapping().Comparer;

return comparer == null ? value : comparer.Snapshot(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ protected override int GetPropertyCount(IEntityType entityType)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override ValueComparer GetValueComparer(IProperty property)
=> property.GetValueComparer() ?? property.FindMapping()?.Comparer;
=> property.GetValueComparer() ?? property.GetTypeMapping().Comparer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ protected override int GetPropertyCount(IEntityType entityType)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override ValueComparer GetValueComparer(IProperty property)
=> property.GetKeyValueComparer() ?? property.FindMapping()?.KeyComparer;
=> property.GetKeyValueComparer() ?? property.GetTypeMapping().KeyComparer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private static object SnapshotValue(IPropertyBase propertyBase, object value)
{
if (propertyBase is IProperty property)
{
var comparer = property.GetKeyValueComparer() ?? property.FindMapping()?.KeyComparer;
var comparer = property.GetKeyValueComparer() ?? property.GetTypeMapping().KeyComparer;

if (comparer != null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/SidecarValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void SetValue(IProperty property, object value, int index)

private static object SnapshotValue(IProperty property, object value)
{
var comparer = property.GetValueComparer() ?? property.FindMapping()?.Comparer;
var comparer = property.GetValueComparer() ?? property.GetTypeMapping().Comparer;

return comparer == null ? value : comparer.Snapshot(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ protected override int GetPropertyCount(IEntityType entityType)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override ValueComparer GetValueComparer(IProperty property)
=> property.GetValueComparer() ?? property.FindMapping()?.Comparer;
=> property.GetValueComparer() ?? property.GetTypeMapping().Comparer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public SimplePrincipalKeyValueFactory([NotNull] IProperty property)
_propertyAccessors = _property.GetPropertyAccessors();

var comparer = property.GetKeyValueComparer()
?? property.FindMapping()?.KeyComparer;
?? property.GetTypeMapping().KeyComparer;

EqualityComparer
= comparer != null
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/StateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ private static bool KeysEqual(InternalEntityEntry entry, IForeignKey fk, Interna

private static bool KeyValuesEqual(IProperty property, object value, object currentValue)
=> (property.GetKeyValueComparer()
?? property.FindMapping()?.KeyComparer)
?? property.GetTypeMapping().KeyComparer)
?.Equals(currentValue, value)
?? Equals(currentValue, value);

Expand Down
21 changes: 21 additions & 0 deletions src/EFCore/Extensions/PropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
Expand All @@ -22,6 +24,25 @@ namespace Microsoft.EntityFrameworkCore
/// </summary>
public static class PropertyExtensions
{
/// <summary>
/// Returns the <see cref="CoreTypeMapping" /> for the given property from a finalized model.
/// </summary>
/// <param name="property"> The property. </param>
/// <returns> The type mapping. </returns>
public static CoreTypeMapping GetTypeMapping(
[NotNull] this IProperty property)
{
var mapping = (CoreTypeMapping)property[CoreAnnotationNames.TypeMapping];

if (mapping == null)
{
throw new InvalidOperationException(
CoreStrings.ModelNotFinalized(nameof(GetTypeMapping)));
}

return mapping;
}

/// <summary>
/// Returns the <see cref="CoreTypeMapping" /> for the given property.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Metadata/Internal/ClrPropertyGetterFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ protected override IClrPropertyGetter CreateGeneric<TEntity, TValue, TNonNullabl
{
var property = propertyBase as IProperty;
var comparer = property?.GetValueComparer()
?? property?.FindMapping()?.Comparer
?? property?.GetTypeMapping().Comparer
?? (ValueComparer)Activator.CreateInstance(
typeof(ValueComparer<>).MakeGenericType(typeof(TValue)),
new object[]
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Metadata/Internal/EntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2355,7 +2355,7 @@ public virtual IEnumerable<IDictionary<string, object>> GetSeedData(bool provide
{
if (propertyBase is IProperty property)
{
valueConverter = property.FindMapping()?.Converter
valueConverter = property.GetTypeMapping().Converter
?? property.GetValueConverter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected override IClrPropertyGetter CreateGeneric<TEntity, TValue, TNonNullabl
var comparer = typeof(TValue).IsNullableType()
? null
: property?.GetValueComparer()
?? property?.FindMapping()?.Comparer
?? property?.GetTypeMapping().Comparer
?? (ValueComparer)Activator.CreateInstance(
typeof(ValueComparer<>).MakeGenericType(typeof(TValue)),
new object[]
Expand Down
10 changes: 9 additions & 1 deletion src/EFCore/Properties/CoreStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit dfe3110

Please sign in to comment.