Skip to content

Commit

Permalink
Cache property and field infos
Browse files Browse the repository at this point in the history
Memoize DisplayName() for Type
Call Attribute.IsDefined before GetCustomAttributes()
Use in parameters for TypeMappingInfo and RelationalTypeMappingInfo
Implement IEquatable<T> on TypeMappingInfo and RelationalTypeMappingInfo

Fixes #9347
  • Loading branch information
AndriySvyryd committed Apr 2, 2018
1 parent 1d2178f commit 5db649a
Show file tree
Hide file tree
Showing 50 changed files with 501 additions and 345 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public OracleTypeMappingSource(
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
var mapping = FindRawMapping(mappingInfo)?.Clone(mappingInfo);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public FallbackRelationalTypeMappingSource(
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override RelationalTypeMapping FindMappingWithConversion(
RelationalTypeMappingInfo mappingInfo,
in RelationalTypeMappingInfo mappingInfo,
IProperty property)
{
_property = property;
Expand All @@ -53,7 +53,7 @@ protected override RelationalTypeMapping FindMappingWithConversion(
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));

Expand Down Expand Up @@ -83,12 +83,12 @@ protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo m
return mapping;
}

private RelationalTypeMapping FindMappingForProperty(RelationalTypeMappingInfo mappingInfo)
private RelationalTypeMapping FindMappingForProperty(in RelationalTypeMappingInfo mappingInfo)
=> _property != null
? _relationalTypeMapper.FindMapping(_property)
: null;

private RelationalTypeMapping FindMappingForClrType(RelationalTypeMappingInfo mappingInfo)
private RelationalTypeMapping FindMappingForClrType(in RelationalTypeMappingInfo mappingInfo)
{
if (mappingInfo.ClrType == null
|| (mappingInfo.StoreTypeName != null
Expand Down Expand Up @@ -118,7 +118,7 @@ private RelationalTypeMapping FindMappingForClrType(RelationalTypeMappingInfo ma
return _relationalTypeMapper.FindMapping(mappingInfo.ClrType);
}

private RelationalTypeMapping FindMappingForStoreTypeName(RelationalTypeMappingInfo mappingInfo)
private RelationalTypeMapping FindMappingForStoreTypeName(in RelationalTypeMappingInfo mappingInfo)
{
if (mappingInfo.StoreTypeName != null)
{
Expand All @@ -130,7 +130,7 @@ private RelationalTypeMapping FindMappingForStoreTypeName(RelationalTypeMappingI
return null;
}

private static RelationalTypeMapping FilterByClrType(RelationalTypeMapping mapping, RelationalTypeMappingInfo mappingInfo)
private static RelationalTypeMapping FilterByClrType(RelationalTypeMapping mapping, in RelationalTypeMappingInfo mappingInfo)
=> mapping != null
&& (mappingInfo.ClrType == null
|| mappingInfo.ClrType == mapping.ClrType)
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Relational/Storage/RelationalTypeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public override CoreTypeMapping Clone(ValueConverter converter)
/// </summary>
/// <param name="mappingInfo"> The mapping info containing the facets to use. </param>
/// <returns> The cloned mapping, or the original mapping if no clone was needed. </returns>
public virtual RelationalTypeMapping Clone(RelationalTypeMappingInfo mappingInfo)
public virtual RelationalTypeMapping Clone(in RelationalTypeMappingInfo mappingInfo)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));

Expand Down
15 changes: 8 additions & 7 deletions src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
/// Describes metadata needed to decide on a relational type mapping for
/// a property, type, or provider-specific relational type name.
/// </summary>
public readonly struct RelationalTypeMappingInfo
public readonly struct RelationalTypeMappingInfo : IEquatable<RelationalTypeMappingInfo>
{
private readonly TypeMappingInfo _coreTypeMappingInfo;
private readonly int? _parsedSize;
Expand Down Expand Up @@ -88,11 +88,12 @@ public RelationalTypeMappingInfo([NotNull] MemberInfo member)

_coreTypeMappingInfo = new TypeMappingInfo(member);

var attribute = member.GetCustomAttributes<ColumnAttribute>(true)?.FirstOrDefault();
if (attribute != null)
if (Attribute.IsDefined(member, typeof(ColumnAttribute), inherit: true))
{
var attribute = member.GetCustomAttributes<ColumnAttribute>(inherit: true).First();
StoreTypeName = attribute.TypeName;
StoreTypeNameBase = ParseStoreTypeName(attribute.TypeName, out _parsedSize, out _parsedPrecision, out _parsedScale, out _isMax);
StoreTypeNameBase = ParseStoreTypeName(
attribute.TypeName, out _parsedSize, out _parsedPrecision, out _parsedScale, out _isMax);
}
else
{
Expand All @@ -113,8 +114,8 @@ public RelationalTypeMappingInfo([NotNull] MemberInfo member)
/// <param name="source"> The source info. </param>
/// <param name="converter"> The converter to apply. </param>
public RelationalTypeMappingInfo(
RelationalTypeMappingInfo source,
ValueConverterInfo converter)
in RelationalTypeMappingInfo source,
in ValueConverterInfo converter)
{
_coreTypeMappingInfo = new TypeMappingInfo(
source._coreTypeMappingInfo,
Expand Down Expand Up @@ -277,7 +278,7 @@ private static string ParseStoreTypeName(
/// </summary>
/// <param name="converterInfo"> The converter to apply. </param>
/// <returns> The new mapping info. </returns>
public RelationalTypeMappingInfo WithConverter(ValueConverterInfo converterInfo)
public RelationalTypeMappingInfo WithConverter(in ValueConverterInfo converterInfo)
=> new RelationalTypeMappingInfo(this, converterInfo);

/// <summary>
Expand Down
22 changes: 12 additions & 10 deletions src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.EntityFrameworkCore.Utilities;

#pragma warning disable 1574
#pragma warning disable CS0419 // Ambiguous reference in cref attribute
namespace Microsoft.EntityFrameworkCore.Storage
{
/// <summary>
/// <para>
/// The base class for non-relational type mapping starting with version 2.1. Non-relational providers
/// should derive from this class and override <see cref="FindMapping(RelationalTypeMappingInfo)" />
/// The base class for relational type mapping starting with version 2.1. Relational providers
/// should derive from this class and override <see cref="RelationalTypeMappingSource.FindMapping" />
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
Expand Down Expand Up @@ -56,27 +58,27 @@ protected RelationalTypeMappingSource(
/// </summary>
/// <param name="mappingInfo"> The mapping info to use to create the mapping. </param>
/// <returns> The type mapping, or <c>null</c> if none could be found. </returns>
protected abstract RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo);
protected abstract RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo);

/// <summary>
/// Dependencies used to create this <see cref="RelationalTypeMappingSource" />
/// </summary>
protected virtual RelationalTypeMappingSourceDependencies RelationalDependencies { get; }

/// <summary>
/// Overridden to call <see cref="FindMapping(RelationalTypeMappingInfo)" />
/// Call <see cref="RelationalTypeMappingSource.FindMapping" /> instead
/// </summary>
/// <param name="mappingInfo"> The mapping info to use to create the mapping. </param>
/// <returns> The type mapping, or <c>null</c> if none could be found. </returns>
protected override CoreTypeMapping FindMapping(TypeMappingInfo mappingInfo)
protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
=> throw new InvalidOperationException("FindMapping on a 'RelationalTypeMappingSource' with a non-relational 'TypeMappingInfo'.");

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected virtual RelationalTypeMapping FindMappingWithConversion(
RelationalTypeMappingInfo mappingInfo,
in RelationalTypeMappingInfo mappingInfo,
[CanBeNull] IProperty property)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));
Expand All @@ -97,21 +99,21 @@ protected virtual RelationalTypeMapping FindMappingWithConversion(
k =>
{
var mapping = providerClrType == null
|| providerClrType == mappingInfo.ClrType
? FindMapping(mappingInfo)
|| providerClrType == k.ClrType
? FindMapping(k)
: null;

if (mapping == null)
{
var sourceType = mappingInfo.ClrType;
var sourceType = k.ClrType;

if (sourceType != null)
{
foreach (var converterInfo in Dependencies
.ValueConverterSelector
.Select(sourceType, providerClrType))
{
var mappingInfoUsed = mappingInfo.WithConverter(converterInfo);
var mappingInfoUsed = k.WithConverter(converterInfo);
mapping = FindMapping(mappingInfoUsed);

if (mapping == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ protected override void ValidateMapping(CoreTypeMapping mapping, IProperty prope
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
=> FindRawMapping(mappingInfo)?.Clone(mappingInfo);

private RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public SqliteTypeMappingSource(
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
var clrType = mappingInfo.ClrType;
if (clrType != null
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Extensions/MutableModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static IMutableEntityType RemoveEntityType([NotNull] this IMutableModel m
Check.NotNull(model, nameof(model));
Check.NotNull(type, nameof(type));

return model.RemoveEntityType(type.DisplayName());
return model.AsModel().RemoveEntityType(type);
}

/// <summary>
Expand Down
16 changes: 10 additions & 6 deletions src/EFCore/Infrastructure/ModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -511,12 +511,7 @@ protected virtual void ValidateData([NotNull] IModel model)
foreach (var entityType in model.GetEntityTypes().Where(et => !et.IsQueryType))
{
var key = entityType.FindPrimaryKey();
if (!identityMaps.TryGetValue(key, out var identityMap))
{
identityMap = key.GetIdentityMapFactory()(sensitiveDataLogged);
identityMaps[key] = identityMap;
}

IIdentityMap identityMap = null;
foreach (var seedDatum in entityType.GetData())
{
foreach (var property in entityType.GetProperties())
Expand Down Expand Up @@ -578,6 +573,15 @@ protected virtual void ValidateData([NotNull] IModel model)
}
}

if (identityMap == null)
{
if (!identityMaps.TryGetValue(key, out identityMap))
{
identityMap = key.GetIdentityMapFactory()(sensitiveDataLogged);
identityMaps[key] = identityMap;
}
}

var entry = identityMap.TryGetEntry(keyValues);
if (entry != null)
{
Expand Down
6 changes: 3 additions & 3 deletions src/EFCore/Metadata/Builders/EntityTypeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ public virtual ReferenceOwnershipBuilder OwnsOne(
[NotNull] Type ownedType,
[NotNull] string navigationName)
=> OwnsOneBuilder(
new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType))),
new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType)), (Model)Metadata.Model),
Check.NotEmpty(navigationName, nameof(navigationName)));

/// <summary>
Expand Down Expand Up @@ -278,7 +278,7 @@ public virtual EntityTypeBuilder OwnsOne(

using (Builder.Metadata.Model.ConventionDispatcher.StartBatch())
{
buildAction.Invoke(OwnsOneBuilder(new TypeIdentity(ownedType), navigationName));
buildAction.Invoke(OwnsOneBuilder(new TypeIdentity(ownedType, (Model)Metadata.Model), navigationName));
return this;
}
}
Expand Down Expand Up @@ -311,7 +311,7 @@ public virtual EntityTypeBuilder OwnsOne(
}
}

private ReferenceOwnershipBuilder OwnsOneBuilder(TypeIdentity ownedType, string navigationName)
private ReferenceOwnershipBuilder OwnsOneBuilder(in TypeIdentity ownedType, string navigationName)
{
InternalRelationshipBuilder relationship;
using (Builder.Metadata.Model.ConventionDispatcher.StartBatch())
Expand Down
6 changes: 3 additions & 3 deletions src/EFCore/Metadata/Builders/ReferenceOwnershipBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ public virtual ReferenceOwnershipBuilder OwnsOne(
[NotNull] Type ownedType,
[NotNull] string navigationName)
=> OwnsOneBuilder(
new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType))),
new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType)), (Model)OwnedEntityType.Model),
Check.NotEmpty(navigationName, nameof(navigationName)));

/// <summary>
Expand Down Expand Up @@ -339,7 +339,7 @@ public virtual ReferenceOwnershipBuilder OwnsOne(

using (DeclaringEntityType.Model.ConventionDispatcher.StartBatch())
{
buildAction.Invoke(OwnsOneBuilder(new TypeIdentity(ownedType), navigationName));
buildAction.Invoke(OwnsOneBuilder(new TypeIdentity(ownedType, (Model)OwnedEntityType.Model), navigationName));
return this;
}
}
Expand Down Expand Up @@ -380,7 +380,7 @@ public virtual ReferenceOwnershipBuilder OwnsOne(
}
}

private ReferenceOwnershipBuilder OwnsOneBuilder(TypeIdentity ownedType, string navigationName)
private ReferenceOwnershipBuilder OwnsOneBuilder(in TypeIdentity ownedType, string navigationName)
{
InternalRelationshipBuilder relationship;
using (RelatedEntityType.Model.ConventionDispatcher.StartBatch())
Expand Down
29 changes: 17 additions & 12 deletions src/EFCore/Metadata/Conventions/Internal/BackingFieldConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ protected virtual void Apply([NotNull] PropertyBase propertyBase)
var type = propertyBase.DeclaringType.ClrType;
while (type != null)
{
var fieldInfo = TryMatchFieldName(type, propertyBase.ClrType, propertyBase.Name);
var fieldInfo = TryMatchFieldName(
(Model)propertyBase.DeclaringType.Model, type, propertyBase.ClrType,propertyBase.Name);
if (fieldInfo != null)
{
propertyBase.SetFieldInfo(fieldInfo, ConfigurationSource.Convention);
Expand All @@ -60,22 +61,26 @@ protected virtual void Apply([NotNull] PropertyBase propertyBase)
}
}

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected virtual FieldInfo TryMatchFieldName(
[NotNull] Type entityType, [NotNull] Type propertyType, [NotNull] string propertyName)
private FieldInfo TryMatchFieldName(Model model, Type entityClrType, Type propertyType, string propertyName)
{
var fields = new Dictionary<string, FieldInfo>();
foreach (var field in entityType.GetRuntimeFields())
Dictionary<string, FieldInfo> fields;
var entityType = model.FindEntityType(entityClrType);
if (entityType == null)
{
if (!field.IsStatic
&& !fields.ContainsKey(field.Name))
fields = new Dictionary<string, FieldInfo>();
foreach (var field in entityClrType.GetRuntimeFields())
{
fields[field.Name] = field;
if (!field.IsStatic
&& !fields.ContainsKey(field.Name))
{
fields[field.Name] = field;
}
}
}
else
{
fields = entityType.GetRuntimeFields();
}

var sortedFields = fields.OrderBy(p => p.Key, StringComparer.Ordinal).ToArray();

Expand Down
28 changes: 28 additions & 0 deletions src/EFCore/Metadata/Conventions/Internal/CacheCleanupConvention.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal
{
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class CacheCleanupConvention : IModelBuiltConvention
{
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public virtual InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
{
entityType.ClearCaches();
}

return modelBuilder;
}
}
}
Loading

0 comments on commit 5db649a

Please sign in to comment.