diff --git a/samples/OracleProvider/src/OracleProvider/Storage/Internal/OracleTypeMappingSource.cs b/samples/OracleProvider/src/OracleProvider/Storage/Internal/OracleTypeMappingSource.cs
index ab93cefe78b..a0a1af4086e 100644
--- a/samples/OracleProvider/src/OracleProvider/Storage/Internal/OracleTypeMappingSource.cs
+++ b/samples/OracleProvider/src/OracleProvider/Storage/Internal/OracleTypeMappingSource.cs
@@ -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.
///
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
var mapping = FindRawMapping(mappingInfo)?.Clone(mappingInfo);
diff --git a/src/EFCore.Relational/Storage/Internal/FallbackRelationalTypeMappingSource.cs b/src/EFCore.Relational/Storage/Internal/FallbackRelationalTypeMappingSource.cs
index 82762cbaab8..198e5cb0699 100644
--- a/src/EFCore.Relational/Storage/Internal/FallbackRelationalTypeMappingSource.cs
+++ b/src/EFCore.Relational/Storage/Internal/FallbackRelationalTypeMappingSource.cs
@@ -41,7 +41,7 @@ public FallbackRelationalTypeMappingSource(
/// directly from your code. This API may change or be removed in future releases.
///
protected override RelationalTypeMapping FindMappingWithConversion(
- RelationalTypeMappingInfo mappingInfo,
+ in RelationalTypeMappingInfo mappingInfo,
IProperty property)
{
_property = property;
@@ -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.
///
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));
@@ -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
@@ -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)
{
@@ -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)
diff --git a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
index 86f823cd1d2..ff8a1623811 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
@@ -295,7 +295,7 @@ public override CoreTypeMapping Clone(ValueConverter converter)
///
/// The mapping info containing the facets to use.
/// The cloned mapping, or the original mapping if no clone was needed.
- public virtual RelationalTypeMapping Clone(RelationalTypeMappingInfo mappingInfo)
+ public virtual RelationalTypeMapping Clone(in RelationalTypeMappingInfo mappingInfo)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));
diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
index 43537d85468..2cabbb8fc82 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
@@ -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.
///
- public readonly struct RelationalTypeMappingInfo
+ public readonly struct RelationalTypeMappingInfo : IEquatable
{
private readonly TypeMappingInfo _coreTypeMappingInfo;
private readonly int? _parsedSize;
@@ -88,11 +88,12 @@ public RelationalTypeMappingInfo([NotNull] MemberInfo member)
_coreTypeMappingInfo = new TypeMappingInfo(member);
- var attribute = member.GetCustomAttributes(true)?.FirstOrDefault();
- if (attribute != null)
+ if (Attribute.IsDefined(member, typeof(ColumnAttribute), inherit: true))
{
+ var attribute = member.GetCustomAttributes(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
{
@@ -113,8 +114,8 @@ public RelationalTypeMappingInfo([NotNull] MemberInfo member)
/// The source info.
/// The converter to apply.
public RelationalTypeMappingInfo(
- RelationalTypeMappingInfo source,
- ValueConverterInfo converter)
+ in RelationalTypeMappingInfo source,
+ in ValueConverterInfo converter)
{
_coreTypeMappingInfo = new TypeMappingInfo(
source._coreTypeMappingInfo,
@@ -277,7 +278,7 @@ private static string ParseStoreTypeName(
///
/// The converter to apply.
/// The new mapping info.
- public RelationalTypeMappingInfo WithConverter(ValueConverterInfo converterInfo)
+ public RelationalTypeMappingInfo WithConverter(in ValueConverterInfo converterInfo)
=> new RelationalTypeMappingInfo(this, converterInfo);
///
diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
index 4ca3b62e39f..07ead62fd4f 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
@@ -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
{
///
///
- /// The base class for non-relational type mapping starting with version 2.1. Non-relational providers
- /// should derive from this class and override
+ /// The base class for relational type mapping starting with version 2.1. Relational providers
+ /// should derive from this class and override
///
///
/// This type is typically used by database providers (and other extensions). It is generally
@@ -56,7 +58,7 @@ protected RelationalTypeMappingSource(
///
/// The mapping info to use to create the mapping.
/// The type mapping, or null if none could be found.
- protected abstract RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo);
+ protected abstract RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo);
///
/// Dependencies used to create this
@@ -64,11 +66,11 @@ protected RelationalTypeMappingSource(
protected virtual RelationalTypeMappingSourceDependencies RelationalDependencies { get; }
///
- /// Overridden to call
+ /// Call instead
///
/// The mapping info to use to create the mapping.
/// The type mapping, or null if none could be found.
- 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'.");
///
@@ -76,7 +78,7 @@ protected override CoreTypeMapping FindMapping(TypeMappingInfo mappingInfo)
/// directly from your code. This API may change or be removed in future releases.
///
protected virtual RelationalTypeMapping FindMappingWithConversion(
- RelationalTypeMappingInfo mappingInfo,
+ in RelationalTypeMappingInfo mappingInfo,
[CanBeNull] IProperty property)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));
@@ -97,13 +99,13 @@ 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)
{
@@ -111,7 +113,7 @@ protected virtual RelationalTypeMapping FindMappingWithConversion(
.ValueConverterSelector
.Select(sourceType, providerClrType))
{
- var mappingInfoUsed = mappingInfo.WithConverter(converterInfo);
+ var mappingInfoUsed = k.WithConverter(converterInfo);
mapping = FindMapping(mappingInfoUsed);
if (mapping == null
diff --git a/src/EFCore.SqlServer/Metadata/SqlServerPropertyAnnotations.cs b/src/EFCore.SqlServer/Metadata/SqlServerPropertyAnnotations.cs
index 4d6947b24ac..93a378a5ed6 100644
--- a/src/EFCore.SqlServer/Metadata/SqlServerPropertyAnnotations.cs
+++ b/src/EFCore.SqlServer/Metadata/SqlServerPropertyAnnotations.cs
@@ -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
diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs
index 5a5c5d0bb0c..84723b6552d 100644
--- a/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs
+++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs
@@ -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.
///
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
=> FindRawMapping(mappingInfo)?.Clone(mappingInfo);
private RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs
index 3f37e0041d0..3910687fb04 100644
--- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs
+++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs
@@ -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.
///
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
var clrType = mappingInfo.ClrType;
if (clrType != null
diff --git a/src/EFCore/Extensions/MutableModelExtensions.cs b/src/EFCore/Extensions/MutableModelExtensions.cs
index f915412a691..ea332bfb0f3 100644
--- a/src/EFCore/Extensions/MutableModelExtensions.cs
+++ b/src/EFCore/Extensions/MutableModelExtensions.cs
@@ -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);
}
///
diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs
index ab824438054..1b558fb071e 100644
--- a/src/EFCore/Infrastructure/ModelValidator.cs
+++ b/src/EFCore/Infrastructure/ModelValidator.cs
@@ -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())
@@ -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)
{
diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs
index 0b39bc8cc58..bb4ad69b239 100644
--- a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs
+++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs
@@ -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)));
///
@@ -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;
}
}
@@ -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())
diff --git a/src/EFCore/Metadata/Builders/ReferenceOwnershipBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceOwnershipBuilder.cs
index f43a4e67d13..947d823823e 100644
--- a/src/EFCore/Metadata/Builders/ReferenceOwnershipBuilder.cs
+++ b/src/EFCore/Metadata/Builders/ReferenceOwnershipBuilder.cs
@@ -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)));
///
@@ -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;
}
}
@@ -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())
diff --git a/src/EFCore/Metadata/Conventions/Internal/BackingFieldConvention.cs b/src/EFCore/Metadata/Conventions/Internal/BackingFieldConvention.cs
index 605e5e971b9..f7b863fdf57 100644
--- a/src/EFCore/Metadata/Conventions/Internal/BackingFieldConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/BackingFieldConvention.cs
@@ -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);
@@ -60,22 +61,26 @@ protected virtual void Apply([NotNull] PropertyBase propertyBase)
}
}
- ///
- /// 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.
- ///
- 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();
- foreach (var field in entityType.GetRuntimeFields())
+ Dictionary fields;
+ var entityType = model.FindEntityType(entityClrType);
+ if (entityType == null)
{
- if (!field.IsStatic
- && !fields.ContainsKey(field.Name))
+ fields = new Dictionary();
+ 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();
diff --git a/src/EFCore/Metadata/Conventions/Internal/CacheCleanupConvention.cs b/src/EFCore/Metadata/Conventions/Internal/CacheCleanupConvention.cs
new file mode 100644
index 00000000000..f0f3cf0768f
--- /dev/null
+++ b/src/EFCore/Metadata/Conventions/Internal/CacheCleanupConvention.cs
@@ -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
+{
+ ///
+ /// 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.
+ ///
+ public class CacheCleanupConvention : IModelBuiltConvention
+ {
+ ///
+ /// 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.
+ ///
+ public virtual InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
+ {
+ foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
+ {
+ entityType.ClearCaches();
+ }
+
+ return modelBuilder;
+ }
+ }
+}
diff --git a/src/EFCore/Metadata/Conventions/Internal/CoreConventionSetBuilder.cs b/src/EFCore/Metadata/Conventions/Internal/CoreConventionSetBuilder.cs
index b3ad000e636..c7507006520 100644
--- a/src/EFCore/Metadata/Conventions/Internal/CoreConventionSetBuilder.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/CoreConventionSetBuilder.cs
@@ -160,6 +160,7 @@ var servicePropertyDiscoveryConvention
conventionSet.ModelBuiltConventions.Add(new RelationshipValidationConvention());
conventionSet.ModelBuiltConventions.Add(foreignKeyPropertyDiscoveryConvention);
conventionSet.ModelBuiltConventions.Add(servicePropertyDiscoveryConvention);
+ conventionSet.ModelBuiltConventions.Add(new CacheCleanupConvention());
conventionSet.NavigationAddedConventions.Add(backingFieldConvention);
conventionSet.NavigationAddedConventions.Add(new RequiredNavigationAttributeConvention(Dependencies.Logger));
diff --git a/src/EFCore/Metadata/Conventions/Internal/EntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/EntityTypeAttributeConvention.cs
index cea16a694de..0b9a3dd712f 100644
--- a/src/EFCore/Metadata/Conventions/Internal/EntityTypeAttributeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/EntityTypeAttributeConvention.cs
@@ -24,7 +24,14 @@ public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityT
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
- var attributes = entityTypeBuilder.Metadata.ClrType?.GetTypeInfo().GetCustomAttributes(true);
+ var type = entityTypeBuilder.Metadata.ClrType;
+ if (type == null
+ || !Attribute.IsDefined(type, typeof(TAttribute), inherit: true))
+ {
+ return entityTypeBuilder;
+ }
+
+ var attributes = type.GetTypeInfo().GetCustomAttributes(true);
if (attributes != null)
{
foreach (var attribute in attributes)
diff --git a/src/EFCore/Metadata/Conventions/Internal/ForeignKeyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/ForeignKeyAttributeConvention.cs
index 17093e55e44..1c1ab06fe65 100644
--- a/src/EFCore/Metadata/Conventions/Internal/ForeignKeyAttributeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/ForeignKeyAttributeConvention.cs
@@ -231,18 +231,16 @@ private static InternalRelationshipBuilder SplitNavigationsToSeparateRelationshi
}
private static InversePropertyAttribute GetInversePropertyAttributeOnNavigation(Navigation navigation)
- {
- return navigation.DeclaringEntityType.ClrType?.GetRuntimeProperties()
- .FirstOrDefault(p => string.Equals(p.Name, navigation.Name, StringComparison.OrdinalIgnoreCase))
- ?.GetCustomAttribute(true);
- }
+ => navigation.DeclaringEntityType.GetRuntimeProperties()?.Values
+ .FirstOrDefault(p => string.Equals(p.Name, navigation.Name, StringComparison.OrdinalIgnoreCase)
+ && Attribute.IsDefined(p, typeof(InversePropertyAttribute), inherit: true))
+ ?.GetCustomAttribute(inherit: true);
private static ForeignKeyAttribute GetForeignKeyAttribute(TypeBase entityType, string propertyName)
- {
- return entityType.ClrType?.GetRuntimeProperties()
- .FirstOrDefault(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase))
- ?.GetCustomAttribute(true);
- }
+ => entityType.GetRuntimeProperties()?.Values
+ .FirstOrDefault(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase)
+ && Attribute.IsDefined(p, typeof(ForeignKeyAttribute), inherit: true))
+ ?.GetCustomAttribute(inherit: true);
[ContractAnnotation("navigationName:null => null")]
private MemberInfo FindForeignKeyAttributeOnProperty(EntityType entityType, string navigationName)
@@ -254,29 +252,31 @@ private MemberInfo FindForeignKeyAttributeOnProperty(EntityType entityType, stri
}
MemberInfo candidateProperty = null;
- var clrType = entityType.ClrType;
- foreach (var memberInfo in clrType.GetRuntimeProperties().Cast()
- .Concat(clrType.GetRuntimeFields()))
+ foreach (var memberInfo in entityType.GetRuntimeProperties().Values.Cast()
+ .Concat(entityType.GetRuntimeFields().Values))
{
- var attribute = memberInfo.GetCustomAttribute(true);
-
- if (attribute != null
- && attribute.Name == navigationName)
+ if (!Attribute.IsDefined(memberInfo, typeof(ForeignKeyAttribute), inherit: true))
{
- if (memberInfo is PropertyInfo propertyInfo
- && FindCandidateNavigationPropertyType(propertyInfo) != null)
- {
- continue;
- }
+ continue;
+ }
- if (candidateProperty != null)
- {
- throw new InvalidOperationException(CoreStrings.CompositeFkOnProperty(navigationName, entityType.DisplayName()));
- }
+ var attribute = memberInfo.GetCustomAttribute(inherit: true);
- candidateProperty = memberInfo;
+ if (attribute.Name != navigationName
+ || (memberInfo is PropertyInfo propertyInfo
+ && FindCandidateNavigationPropertyType(propertyInfo) != null))
+ {
+ continue;
+ }
+
+ if (candidateProperty != null)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.CompositeFkOnProperty(navigationName,entityType.DisplayName()));
}
+
+ candidateProperty = memberInfo;
}
if (candidateProperty != null)
@@ -327,18 +327,22 @@ private static IReadOnlyList FindCandidateDependentPropertiesThroughNavi
CoreStrings.InvalidPropertyListOnNavigation(navigation.Name, navigation.DeclaringEntityType.DisplayName()));
}
- var navigationPropertyTargetType = navigation.DeclaringEntityType.ClrType.GetRuntimeProperties()
- .Single(p => p.Name == navigation.Name).PropertyType;
+ var navigationPropertyTargetType =
+ navigation.DeclaringEntityType.GetRuntimeProperties()[navigation.Name].PropertyType;
- var otherNavigations = navigation.DeclaringEntityType.ClrType.GetRuntimeProperties()
+ var otherNavigations = navigation.DeclaringEntityType.GetRuntimeProperties().Values
.Where(p => p.PropertyType == navigationPropertyTargetType && p.Name != navigation.Name)
.OrderBy(p => p.Name);
foreach (var propertyInfo in otherNavigations)
{
+ if (!Attribute.IsDefined(propertyInfo, typeof(ForeignKeyAttribute), inherit: true))
+ {
+ continue;
+ }
+
var attribute = propertyInfo.GetCustomAttribute(true);
- if (attribute != null
- && attribute.Name == navigationFkAttribute.Name)
+ if (attribute.Name == navigationFkAttribute.Name)
{
throw new InvalidOperationException(
CoreStrings.MultipleNavigationsSameFk(navigation.DeclaringEntityType.DisplayName(), attribute.Name));
diff --git a/src/EFCore/Metadata/Conventions/Internal/InversePropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/InversePropertyAttributeConvention.cs
index d85885f6d6f..128c5876762 100644
--- a/src/EFCore/Metadata/Conventions/Internal/InversePropertyAttributeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/InversePropertyAttributeConvention.cs
@@ -82,7 +82,8 @@ private InternalRelationshipBuilder ConfigureInverseNavigation(
{
var entityType = entityTypeBuilder.Metadata;
var targetClrType = targetEntityTypeBuilder.Metadata.ClrType;
- var inverseNavigationPropertyInfo = targetClrType.GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, attribute.Property, StringComparison.OrdinalIgnoreCase));
+ var inverseNavigationPropertyInfo = targetEntityTypeBuilder.Metadata.GetRuntimeProperties().Values
+ .FirstOrDefault(p => string.Equals(p.Name, attribute.Property, StringComparison.OrdinalIgnoreCase));
if (inverseNavigationPropertyInfo == null
|| !FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo).GetTypeInfo()
@@ -104,16 +105,18 @@ private InternalRelationshipBuilder ConfigureInverseNavigation(
}
// Check for InversePropertyAttribute on the inverseNavigation to verify that it matches.
- var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute(true);
- if (inverseAttribute != null
- && inverseAttribute.Property != navigationMemberInfo.Name)
+ if (Attribute.IsDefined(inverseNavigationPropertyInfo, typeof(InversePropertyAttribute)))
{
- throw new InvalidOperationException(
- CoreStrings.InversePropertyMismatch(
- navigationMemberInfo.Name,
- entityType.DisplayName(),
- inverseNavigationPropertyInfo.Name,
- targetEntityTypeBuilder.Metadata.DisplayName()));
+ var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute(true);
+ if (inverseAttribute.Property != navigationMemberInfo.Name)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.InversePropertyMismatch(
+ navigationMemberInfo.Name,
+ entityType.DisplayName(),
+ inverseNavigationPropertyInfo.Name,
+ targetEntityTypeBuilder.Metadata.DisplayName()));
+ }
}
var referencingNavigationsWithAttribute =
@@ -153,7 +156,7 @@ private InternalRelationshipBuilder ConfigureInverseNavigation(
{
_logger.NonDefiningInverseNavigationWarning(entityType, navigationMemberInfo,
targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo,
- targetClrType.GetRuntimeProperties().First(p => p.Name == entityType.DefiningNavigationName));
+ targetEntityTypeBuilder.Metadata.GetRuntimeProperties()[entityType.DefiningNavigationName]);
return null;
}
diff --git a/src/EFCore/Metadata/Conventions/Internal/KeyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/KeyAttributeConvention.cs
index 94e6c677e4b..1abf9977c97 100644
--- a/src/EFCore/Metadata/Conventions/Internal/KeyAttributeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/KeyAttributeConvention.cs
@@ -36,7 +36,10 @@ public override InternalPropertyBuilder Apply(
var entityTypeBuilder = entityType.Builder;
var currentKey = entityTypeBuilder.Metadata.FindPrimaryKey();
- var properties = new List { propertyBuilder.Metadata.Name };
+ var properties = new List
+ {
+ propertyBuilder.Metadata.Name
+ };
if (currentKey != null
&& entityType.GetPrimaryKeyConfigurationSource() == ConfigurationSource.DataAnnotation)
@@ -81,8 +84,9 @@ public virtual InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
foreach (var declaredProperty in entityType.GetDeclaredProperties())
{
var memberInfo = declaredProperty.GetIdentifyingMemberInfo();
- var attributes = memberInfo?.GetCustomAttributes(true);
- if (attributes?.Any() == true)
+
+ if (memberInfo != null
+ && Attribute.IsDefined(memberInfo, typeof(KeyAttribute), inherit: true))
{
throw new InvalidOperationException(
CoreStrings.KeyAttributeOnDerivedEntity(entityType.DisplayName(), declaredProperty.Name));
diff --git a/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeEntityTypeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeEntityTypeConvention.cs
index 709c288e256..11d8e0848fd 100644
--- a/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeEntityTypeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeEntityTypeConvention.cs
@@ -5,6 +5,7 @@
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Utilities;
@@ -53,23 +54,21 @@ public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityT
return entityTypeBuilder;
}
- foreach (var navigationPropertyInfo in entityType.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
+ foreach (var navigationPropertyInfo in entityType.GetRuntimeProperties().Values.OrderBy(p => p.Name))
{
var targetClrType = FindCandidateNavigationPropertyType(navigationPropertyInfo);
- if (targetClrType == null)
+ if (targetClrType == null
+ || !Attribute.IsDefined(navigationPropertyInfo, typeof(TAttribute), inherit: true))
{
continue;
}
- var attributes = navigationPropertyInfo.GetCustomAttributes(true);
- if (attributes != null)
+ var attributes = navigationPropertyInfo.GetCustomAttributes(inherit: true);
+ foreach (var attribute in attributes)
{
- foreach (var attribute in attributes)
+ if (Apply(entityTypeBuilder, navigationPropertyInfo, targetClrType, attribute) == null)
{
- if (Apply(entityTypeBuilder, navigationPropertyInfo, targetClrType, attribute) == null)
- {
- return null;
- }
+ return null;
}
}
}
@@ -91,20 +90,18 @@ public virtual bool Apply(InternalModelBuilder modelBuilder, string name, Type t
foreach (var navigationPropertyInfo in type.GetRuntimeProperties().OrderBy(p => p.Name))
{
var targetClrType = FindCandidateNavigationPropertyType(navigationPropertyInfo);
- if (targetClrType == null)
+ if (targetClrType == null
+ || !Attribute.IsDefined(navigationPropertyInfo, typeof(TAttribute), inherit: true))
{
continue;
}
var attributes = navigationPropertyInfo.GetCustomAttributes(true);
- if (attributes != null)
+ foreach (var attribute in attributes)
{
- foreach (var attribute in attributes)
+ if (!Apply(modelBuilder, type, navigationPropertyInfo, targetClrType, attribute))
{
- if (!Apply(modelBuilder, type, navigationPropertyInfo, targetClrType, attribute))
- {
- return false;
- }
+ return false;
}
}
}
@@ -116,24 +113,23 @@ public virtual bool Apply(InternalModelBuilder modelBuilder, string name, Type t
/// 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.
///
- public virtual InternalRelationshipBuilder Apply(InternalRelationshipBuilder relationshipBuilder, Navigation navigation)
+ public virtual InternalRelationshipBuilder Apply(
+ InternalRelationshipBuilder relationshipBuilder, Navigation navigation)
{
var navigationPropertyInfo = navigation.GetIdentifyingMemberInfo();
- if (navigationPropertyInfo == null)
+ if (navigationPropertyInfo == null
+ || !Attribute.IsDefined(navigationPropertyInfo, typeof(TAttribute), inherit: true))
{
return relationshipBuilder;
}
var attributes = navigationPropertyInfo.GetCustomAttributes(true);
- if (attributes != null)
+ foreach (var attribute in attributes)
{
- foreach (var attribute in attributes)
+ relationshipBuilder = Apply(relationshipBuilder, navigation, attribute);
+ if (relationshipBuilder == null)
{
- relationshipBuilder = Apply(relationshipBuilder, navigation, attribute);
- if (relationshipBuilder == null)
- {
- return null;
- }
+ return null;
}
}
@@ -146,29 +142,27 @@ public virtual InternalRelationshipBuilder Apply(InternalRelationshipBuilder rel
///
public virtual bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
{
- var clrType = entityTypeBuilder.Metadata.ClrType;
- if (clrType == null)
+ var entityType = entityTypeBuilder.Metadata;
+ if (!entityType.HasClrType())
{
return true;
}
- foreach (var navigationPropertyInfo in clrType.GetRuntimeProperties().OrderBy(p => p.Name))
+ foreach (var navigationPropertyInfo in entityType.GetRuntimeProperties().Values.OrderBy(p => p.Name))
{
var targetClrType = FindCandidateNavigationPropertyType(navigationPropertyInfo);
- if (targetClrType == null)
+ if (targetClrType == null
+ || !Attribute.IsDefined(navigationPropertyInfo, typeof(TAttribute), inherit: true))
{
continue;
}
var attributes = navigationPropertyInfo.GetCustomAttributes(true);
- if (attributes != null)
+ foreach (var attribute in attributes)
{
- foreach (var attribute in attributes)
+ if (!Apply(entityTypeBuilder, oldBaseType, navigationPropertyInfo, targetClrType, attribute))
{
- if (!Apply(entityTypeBuilder, oldBaseType, navigationPropertyInfo, targetClrType, attribute))
- {
- return false;
- }
+ return false;
}
}
}
@@ -183,27 +177,25 @@ public virtual bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityTyp
public virtual bool Apply(InternalEntityTypeBuilder entityTypeBuilder, string ignoredMemberName)
{
var navigationPropertyInfo =
- entityTypeBuilder.Metadata.ClrType.GetRuntimeProperties().FirstOrDefault(p => p.Name == ignoredMemberName);
+ entityTypeBuilder.Metadata.GetRuntimeProperties()?.Find(ignoredMemberName);
if (navigationPropertyInfo == null)
{
return true;
}
var targetClrType = FindCandidateNavigationPropertyType(navigationPropertyInfo);
- if (targetClrType == null)
+ if (targetClrType == null
+ || !Attribute.IsDefined(navigationPropertyInfo, typeof(TAttribute), inherit: true))
{
return true;
}
var attributes = navigationPropertyInfo.GetCustomAttributes(true);
- if (attributes != null)
+ foreach (var attribute in attributes)
{
- foreach (var attribute in attributes)
+ if (!ApplyIgnored(entityTypeBuilder, navigationPropertyInfo, targetClrType, attribute))
{
- if (!ApplyIgnored(entityTypeBuilder, navigationPropertyInfo, targetClrType, attribute))
- {
- return false;
- }
+ return false;
}
}
return true;
diff --git a/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeNavigationConvention.cs b/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeNavigationConvention.cs
index b999784e111..a798b56450d 100644
--- a/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeNavigationConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/NavigationAttributeNavigationConvention.cs
@@ -6,6 +6,7 @@
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
@@ -22,24 +23,22 @@ public abstract class NavigationAttributeNavigationConvention : INav
/// 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.
///
- public virtual InternalRelationshipBuilder Apply(InternalRelationshipBuilder relationshipBuilder, Navigation navigation)
+ public virtual InternalRelationshipBuilder Apply(InternalRelationshipBuilder relationshipBuilder,
+ Navigation navigation)
{
Check.NotNull(relationshipBuilder, nameof(relationshipBuilder));
Check.NotNull(navigation, nameof(navigation));
var attributes = GetAttributes(navigation.DeclaringEntityType, navigation.Name);
-
- if (attributes != null)
+ foreach (var attribute in attributes)
{
- foreach (var attribute in attributes)
+ relationshipBuilder = Apply(relationshipBuilder, navigation, attribute);
+ if (relationshipBuilder == null)
{
- relationshipBuilder = Apply(relationshipBuilder, navigation, attribute);
- if (relationshipBuilder == null)
- {
- break;
- }
+ break;
}
}
+
return relationshipBuilder;
}
@@ -47,20 +46,33 @@ public virtual InternalRelationshipBuilder Apply(InternalRelationshipBuilder rel
/// 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.
///
- public abstract InternalRelationshipBuilder Apply([NotNull] InternalRelationshipBuilder relationshipBuilder, [NotNull] Navigation navigation, [NotNull] TAttribute attribute);
+ public abstract InternalRelationshipBuilder Apply([NotNull] InternalRelationshipBuilder relationshipBuilder,
+ [NotNull] Navigation navigation, [NotNull] TAttribute attribute);
///
/// 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.
///
- protected static IEnumerable GetAttributes([NotNull] EntityType entityType, [NotNull] string propertyName)
+ protected static IEnumerable GetAttributes(
+ [NotNull] EntityType entityType, [NotNull] string propertyName)
where TCustomAttribute : Attribute
{
Check.NotNull(entityType, nameof(entityType));
Check.NotNull(propertyName, nameof(propertyName));
- return entityType.ClrType?.GetRuntimeProperties().FirstOrDefault(p => p.Name == propertyName)
- ?.GetCustomAttributes(true);
+ if (!entityType.HasClrType())
+ {
+ return Enumerable.Empty();
+ }
+
+ var property = entityType.GetRuntimeProperties().Find(propertyName);
+ if (property != null
+ && Attribute.IsDefined(property, typeof(TCustomAttribute), inherit: true))
+ {
+ return property.GetCustomAttributes(true);
+ }
+
+ return Enumerable.Empty();
}
}
}
diff --git a/src/EFCore/Metadata/Conventions/Internal/NotMappedMemberAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/NotMappedMemberAttributeConvention.cs
index 7e101e4eb1f..91171f25895 100644
--- a/src/EFCore/Metadata/Conventions/Internal/NotMappedMemberAttributeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/NotMappedMemberAttributeConvention.cs
@@ -1,6 +1,7 @@
// 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 System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
@@ -23,18 +24,18 @@ public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityT
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
- var clrType = entityTypeBuilder.Metadata.ClrType;
- if (clrType == null)
+ var entityType = entityTypeBuilder.Metadata;
+ if (!entityType.HasClrType())
{
return entityTypeBuilder;
}
- var members = clrType.GetRuntimeProperties().Cast().Concat(clrType.GetRuntimeFields());
+ var members = entityType.GetRuntimeProperties().Values.Cast()
+ .Concat(entityType.GetRuntimeFields().Values);
foreach (var member in members)
{
- var attributes = member.GetCustomAttributes(inherit: true);
- if (attributes.Any())
+ if (Attribute.IsDefined(member, typeof(NotMappedAttribute), inherit: true))
{
entityTypeBuilder.Ignore(member.Name, ConfigurationSource.DataAnnotation);
}
diff --git a/src/EFCore/Metadata/Conventions/Internal/PropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/PropertyAttributeConvention.cs
index 5f9b7c0c5d0..9c8a4f7acd1 100644
--- a/src/EFCore/Metadata/Conventions/Internal/PropertyAttributeConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/PropertyAttributeConvention.cs
@@ -25,7 +25,17 @@ public virtual InternalPropertyBuilder Apply(InternalPropertyBuilder propertyBui
Check.NotNull(propertyBuilder, nameof(propertyBuilder));
var memberInfo = propertyBuilder.Metadata.GetIdentifyingMemberInfo();
- var attributes = memberInfo?.GetCustomAttributes(true);
+ if (memberInfo == null)
+ {
+ return propertyBuilder;
+ }
+
+ if (!Attribute.IsDefined(memberInfo, typeof(TAttribute), inherit: true))
+ {
+ return propertyBuilder;
+ }
+
+ var attributes = memberInfo.GetCustomAttributes(inherit: true);
if (attributes != null)
{
foreach (var attribute in attributes)
diff --git a/src/EFCore/Metadata/Conventions/Internal/PropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/Internal/PropertyDiscoveryConvention.cs
index fd1a91577c7..9befac37b02 100644
--- a/src/EFCore/Metadata/Conventions/Internal/PropertyDiscoveryConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/PropertyDiscoveryConvention.cs
@@ -40,9 +40,7 @@ public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityT
if (entityType.HasClrType())
{
- var candidates = entityType.ClrType.GetRuntimeProperties();
-
- foreach (var propertyInfo in candidates)
+ foreach (var propertyInfo in entityType.GetRuntimeProperties().Values)
{
if (IsCandidatePrimitiveProperty(propertyInfo))
{
diff --git a/src/EFCore/Metadata/Conventions/Internal/PropertyMappingValidationConvention.cs b/src/EFCore/Metadata/Conventions/Internal/PropertyMappingValidationConvention.cs
index 123e7f68033..24fc5f77c50 100644
--- a/src/EFCore/Metadata/Conventions/Internal/PropertyMappingValidationConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/PropertyMappingValidationConvention.cs
@@ -58,73 +58,80 @@ public virtual InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
entityType.DisplayName(), unmappedProperty.Name, unmappedProperty.ClrType.ShortDisplayName()));
}
- if (entityType.HasClrType())
+ if (!entityType.HasClrType())
{
- var clrProperties = new HashSet();
+ continue;
+ }
+
+ var clrProperties = new HashSet();
- clrProperties.UnionWith(
- entityType.ClrType.GetRuntimeProperties()
- .Where(pi => pi.IsCandidateProperty())
- .Select(pi => pi.Name));
+ clrProperties.UnionWith(
+ entityType.GetRuntimeProperties().Values
+ .Where(pi => pi.IsCandidateProperty())
+ .Select(pi => pi.Name));
- clrProperties.ExceptWith(entityType.GetProperties().Select(p => p.Name));
- clrProperties.ExceptWith(entityType.GetNavigations().Select(p => p.Name));
- clrProperties.ExceptWith(entityType.GetServiceProperties().Select(p => p.Name));
- clrProperties.RemoveWhere(p => entityType.Builder.IsIgnored(p, ConfigurationSource.Convention));
+ clrProperties.ExceptWith(entityType.GetProperties().Select(p => p.Name));
+ clrProperties.ExceptWith(entityType.GetNavigations().Select(p => p.Name));
+ clrProperties.ExceptWith(entityType.GetServiceProperties().Select(p => p.Name));
+ clrProperties.RemoveWhere(p => entityType.Builder.IsIgnored(p, ConfigurationSource.Convention));
+
+ if (clrProperties.Count <= 0)
+ {
+ continue;
+ }
- if (clrProperties.Count > 0)
+ foreach (var clrProperty in clrProperties)
+ {
+ var actualProperty = entityType.GetRuntimeProperties().Find(clrProperty);
+ var propertyType = actualProperty.PropertyType;
+ var targetSequenceType = propertyType.TryGetSequenceType();
+
+ if (modelBuilder.IsIgnored(modelBuilder.Metadata.GetDisplayName(propertyType),
+ ConfigurationSource.Convention)
+ || (targetSequenceType != null
+ && modelBuilder.IsIgnored(modelBuilder.Metadata.GetDisplayName(targetSequenceType),
+ ConfigurationSource.Convention)))
{
- foreach (var clrProperty in clrProperties)
+ continue;
+ }
+
+ var targetType = FindCandidateNavigationPropertyType(actualProperty);
+
+ var isTargetWeakOrOwned
+ = targetType != null
+ && (modelBuilder.Metadata.HasEntityTypeWithDefiningNavigation(targetType)
+ || modelBuilder.Metadata.ShouldBeOwnedType(targetType));
+
+ if (targetType != null
+ && targetType.IsValidEntityType()
+ && (isTargetWeakOrOwned
+ || modelBuilder.Metadata.FindEntityType(targetType) != null
+ || targetType.GetRuntimeProperties().Any(p => p.IsCandidateProperty())))
+ {
+ if ((!isTargetWeakOrOwned
+ || !targetType.GetTypeInfo().Equals(entityType.ClrType.GetTypeInfo()))
+ && entityType.GetDerivedTypes().All(
+ dt => dt.FindDeclaredNavigation(actualProperty.Name) == null)
+ && !entityType.IsInDefinitionPath(targetType))
{
- var actualProperty = entityType.ClrType.GetRuntimeProperties().First(p => p.Name == clrProperty);
- var propertyType = actualProperty.PropertyType;
- var targetSequenceType = propertyType.TryGetSequenceType();
-
- if (modelBuilder.IsIgnored(propertyType.DisplayName(), ConfigurationSource.Convention)
- || (targetSequenceType != null
- && modelBuilder.IsIgnored(targetSequenceType.DisplayName(), ConfigurationSource.Convention)))
- {
- continue;
- }
-
- var targetType = FindCandidateNavigationPropertyType(actualProperty);
-
- var isTargetWeakOrOwned
- = targetType != null
- && (modelBuilder.Metadata.HasEntityTypeWithDefiningNavigation(targetType)
- || modelBuilder.Metadata.ShouldBeOwnedType(targetType));
-
- if (targetType != null
- && targetType.IsValidEntityType()
- && (isTargetWeakOrOwned
- || modelBuilder.Metadata.FindEntityType(targetType) != null
- || targetType.GetRuntimeProperties().Any(p => p.IsCandidateProperty())))
- {
- if ((!isTargetWeakOrOwned
- || !targetType.GetTypeInfo().Equals(entityType.ClrType.GetTypeInfo()))
- && entityType.GetDerivedTypes().All(dt => dt.FindDeclaredNavigation(actualProperty.Name) == null)
- && !entityType.IsInDefinitionPath(targetType))
- {
- throw new InvalidOperationException(
- CoreStrings.NavigationNotAdded(
- entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
- }
- }
- else if (targetSequenceType == null && propertyType.GetTypeInfo().IsInterface
- || targetSequenceType != null && targetSequenceType.GetTypeInfo().IsInterface)
- {
- throw new InvalidOperationException(
- CoreStrings.InterfacePropertyNotAdded(
- entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
- }
- else
- {
- throw new InvalidOperationException(
- CoreStrings.PropertyNotAdded(
- entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
- }
+ throw new InvalidOperationException(
+ CoreStrings.NavigationNotAdded(
+ entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
}
}
+ else if (targetSequenceType == null && propertyType.GetTypeInfo().IsInterface
+ || targetSequenceType != null && targetSequenceType.GetTypeInfo().IsInterface)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.InterfacePropertyNotAdded(
+ entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
+ }
+ else
+ {
+ throw new InvalidOperationException(
+ CoreStrings.PropertyNotAdded(
+ entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
+ }
}
}
diff --git a/src/EFCore/Metadata/Conventions/Internal/RelationshipDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/Internal/RelationshipDiscoveryConvention.cs
index 9eacd7f9c17..e5357f77231 100644
--- a/src/EFCore/Metadata/Conventions/Internal/RelationshipDiscoveryConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/RelationshipDiscoveryConvention.cs
@@ -353,7 +353,7 @@ private static bool IsCompatibleInverse(
var entityType = entityTypeBuilder.Metadata;
var existingNavigation = entityType.FindNavigation(navigationProperty.Name);
if (existingNavigation != null
- && !CanMergeWith(existingNavigation, inversePropertyInfo.Name, targetEntityTypeBuilder))
+ && !CanMergeWith(existingNavigation, inversePropertyInfo, targetEntityTypeBuilder))
{
return false;
}
@@ -362,7 +362,7 @@ private static bool IsCompatibleInverse(
if (existingInverse != null)
{
if (existingInverse.DeclaringEntityType != targetEntityTypeBuilder.Metadata
- || !CanMergeWith(existingInverse, navigationProperty.Name, entityTypeBuilder))
+ || !CanMergeWith(existingInverse, navigationProperty, entityTypeBuilder))
{
return false;
}
@@ -379,12 +379,12 @@ private static bool IsCompatibleInverse(
}
private static bool CanMergeWith(
- Navigation existingNavigation, string inverseName, InternalEntityTypeBuilder inverseEntityTypeBuilder)
+ Navigation existingNavigation, PropertyInfo inverse, InternalEntityTypeBuilder inverseEntityTypeBuilder)
{
var fk = existingNavigation.ForeignKey;
return (fk.IsSelfReferencing()
|| fk.ResolveOtherEntityType(existingNavigation.DeclaringEntityType) == inverseEntityTypeBuilder.Metadata)
- && fk.Builder.CanSetNavigation(inverseName, !existingNavigation.IsDependentToPrincipal(), ConfigurationSource.Convention);
+ && fk.Builder.CanSetNavigation(inverse, !existingNavigation.IsDependentToPrincipal(), ConfigurationSource.Convention);
}
private static IReadOnlyList RemoveInheritedInverseNavigations(
@@ -824,7 +824,7 @@ private ImmutableSortedDictionary GetNavigationCandidates(En
var dictionaryBuilder = ImmutableSortedDictionary.CreateBuilder(MemberInfoNameComparer.Instance);
if (entityType.HasClrType())
{
- foreach (var propertyInfo in entityType.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
+ foreach (var propertyInfo in entityType.GetRuntimeProperties().Values.OrderBy(p => p.Name))
{
var targetType = FindCandidateNavigationPropertyType(propertyInfo);
if (targetType != null)
diff --git a/src/EFCore/Metadata/Conventions/Internal/ServicePropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/Internal/ServicePropertyDiscoveryConvention.cs
index 8090f4f7f3d..4388e35074d 100644
--- a/src/EFCore/Metadata/Conventions/Internal/ServicePropertyDiscoveryConvention.cs
+++ b/src/EFCore/Metadata/Conventions/Internal/ServicePropertyDiscoveryConvention.cs
@@ -57,7 +57,7 @@ public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityT
return entityTypeBuilder;
}
- var candidates = entityType.ClrType.GetRuntimeProperties();
+ var candidates = entityType.GetRuntimeProperties().Values;
foreach (var propertyInfo in candidates)
{
@@ -129,8 +129,8 @@ public virtual bool Apply(InternalEntityTypeBuilder entityTypeBuilder, string ig
return true;
}
- var member = (MemberInfo)entityType.ClrType.GetRuntimeProperties().FirstOrDefault(p => p.Name == ignoredMemberName)
- ?? entityType.ClrType.GetFieldInfo(ignoredMemberName);
+ var member = (MemberInfo)entityType.GetRuntimeProperties().Find(ignoredMemberName)
+ ?? entityType.GetRuntimeFields().Find(ignoredMemberName);
var type = member.GetMemberType();
if (duplicateMap.TryGetValue(type, out var duplicateServiceProperties)
&& duplicateServiceProperties.Remove(member))
diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs
index 25aad44ada9..2b3bfb68c4a 100644
--- a/src/EFCore/Metadata/Internal/EntityType.cs
+++ b/src/EFCore/Metadata/Internal/EntityType.cs
@@ -11,6 +11,7 @@
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.EntityFrameworkCore.Utilities;
@@ -374,6 +375,19 @@ private bool InheritsFrom(EntityType entityType)
///
public override string ToString() => this.ToDebugString();
+ ///
+ /// 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.
+ ///
+ public override void ClearCaches()
+ {
+ base.ClearCaches();
+
+ RemoveAnnotation(RelationshipDiscoveryConvention.AmbiguousNavigationsAnnotationName);
+ RemoveAnnotation(RelationshipDiscoveryConvention.NavigationCandidatesAnnotationName);
+ RemoveAnnotation(InversePropertyAttributeConvention.InverseNavigationsAnnotationName);
+ }
+
///
/// 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.
diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
index f226d18725b..cf3c18f3cf5 100644
--- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
+++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs
@@ -2037,7 +2037,7 @@ public virtual InternalRelationshipBuilder Owns(
[NotNull] string navigationName,
ConfigurationSource configurationSource)
=> Owns(
- new TypeIdentity(targetEntityType),
+ new TypeIdentity(targetEntityType, Metadata.Model),
PropertyIdentity.Create(navigationName),
inverse: null,
configurationSource: configurationSource);
@@ -2051,7 +2051,7 @@ public virtual InternalRelationshipBuilder Owns(
[NotNull] PropertyInfo navigationProperty,
ConfigurationSource configurationSource)
=> Owns(
- new TypeIdentity(targetEntityType),
+ new TypeIdentity(targetEntityType, Metadata.Model),
PropertyIdentity.Create(navigationProperty),
inverse: null,
configurationSource: configurationSource);
@@ -2066,13 +2066,13 @@ public virtual InternalRelationshipBuilder Owns(
[CanBeNull] MemberInfo inverseProperty,
ConfigurationSource configurationSource)
=> Owns(
- new TypeIdentity(targetEntityType),
+ new TypeIdentity(targetEntityType, Metadata.Model),
PropertyIdentity.Create(navigationProperty),
PropertyIdentity.Create(inverseProperty),
configurationSource);
private InternalRelationshipBuilder Owns(
- TypeIdentity targetEntityType,
+ in TypeIdentity targetEntityType,
PropertyIdentity navigation,
PropertyIdentity? inverse,
ConfigurationSource configurationSource)
@@ -2334,11 +2334,8 @@ private IReadOnlyList CreateUniqueProperties(
string baseName)
{
var newProperties = new Property[propertyCount];
- var clrMembers = Metadata.ClrType == null
- ? null
- : new HashSet(
- Metadata.ClrType.GetRuntimeProperties().Select(p => p.Name)
- .Concat(Metadata.ClrType.GetRuntimeFields().Select(p => p.Name)));
+ var clrProperties = Metadata.GetRuntimeProperties();
+ var clrFields = Metadata.GetRuntimeFields();
var noNewProperties = true;
using (var principalPropertyNamesEnumerator = principalPropertyNames.GetEnumerator())
{
@@ -2362,7 +2359,8 @@ private IReadOnlyList CreateUniqueProperties(
{
propertyName = keyModifiedBaseName + (++index > 0 ? index.ToString(CultureInfo.InvariantCulture) : "");
if (!Metadata.FindPropertiesInHierarchy(propertyName).Any()
- && clrMembers?.Contains(propertyName) != true)
+ && clrProperties?.ContainsKey(propertyName) != true
+ && clrFields?.ContainsKey(propertyName) != true)
{
var propertyBuilder = Property(propertyName, clrType, ConfigurationSource.Convention, typeConfigurationSource: null);
if (propertyBuilder == null)
diff --git a/src/EFCore/Metadata/Internal/InternalModelBuilder.cs b/src/EFCore/Metadata/Internal/InternalModelBuilder.cs
index bfcb65dd051..05ec10b254f 100644
--- a/src/EFCore/Metadata/Internal/InternalModelBuilder.cs
+++ b/src/EFCore/Metadata/Internal/InternalModelBuilder.cs
@@ -48,10 +48,10 @@ public virtual InternalEntityTypeBuilder Entity(
///
public virtual InternalEntityTypeBuilder Entity(
[NotNull] Type type, ConfigurationSource configurationSource, bool throwOnQuery = false)
- => Entity(new TypeIdentity(type), configurationSource, throwOnQuery);
+ => Entity(new TypeIdentity(type, Metadata), configurationSource, throwOnQuery);
private InternalEntityTypeBuilder Entity(
- TypeIdentity type, ConfigurationSource configurationSource, bool throwOnQuery)
+ in TypeIdentity type, ConfigurationSource configurationSource, bool throwOnQuery)
{
if (IsIgnored(type, configurationSource))
{
@@ -187,10 +187,10 @@ public virtual InternalEntityTypeBuilder Entity(
[NotNull] string definingNavigationName,
[NotNull] EntityType definingEntityType,
ConfigurationSource configurationSource)
- => Entity(new TypeIdentity(type), definingNavigationName, definingEntityType, configurationSource);
+ => Entity(new TypeIdentity(type, Metadata), definingNavigationName, definingEntityType, configurationSource);
private InternalEntityTypeBuilder Entity(
- TypeIdentity type,
+ in TypeIdentity type,
string definingNavigationName,
EntityType definingEntityType,
ConfigurationSource configurationSource)
@@ -266,9 +266,9 @@ public virtual bool Owned(
///
public virtual bool Owned(
[NotNull] Type type, ConfigurationSource configurationSource)
- => Owned(new TypeIdentity(type), configurationSource);
+ => Owned(new TypeIdentity(type, Metadata), configurationSource);
- private bool Owned(TypeIdentity type, ConfigurationSource configurationSource)
+ private bool Owned(in TypeIdentity type, ConfigurationSource configurationSource)
{
if (IsIgnored(type, configurationSource))
{
@@ -320,7 +320,7 @@ private bool Owned(TypeIdentity type, ConfigurationSource configurationSource)
/// directly from your code. This API may change or be removed in future releases.
///
public virtual bool IsIgnored([NotNull] Type type, ConfigurationSource configurationSource)
- => IsIgnored(new TypeIdentity(type), configurationSource);
+ => IsIgnored(new TypeIdentity(type, Metadata), configurationSource);
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -329,7 +329,7 @@ public virtual bool IsIgnored([NotNull] Type type, ConfigurationSource configura
public virtual bool IsIgnored([NotNull] string name, ConfigurationSource configurationSource)
=> IsIgnored(new TypeIdentity(name), configurationSource);
- private bool IsIgnored(TypeIdentity type, ConfigurationSource configurationSource)
+ private bool IsIgnored(in TypeIdentity type, ConfigurationSource configurationSource)
{
if (configurationSource == ConfigurationSource.Explicit)
{
@@ -346,7 +346,7 @@ private bool IsIgnored(TypeIdentity type, ConfigurationSource configurationSourc
/// directly from your code. This API may change or be removed in future releases.
///
public virtual bool Ignore([NotNull] Type type, ConfigurationSource configurationSource)
- => Ignore(new TypeIdentity(type), configurationSource);
+ => Ignore(new TypeIdentity(type, Metadata), configurationSource);
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -355,7 +355,7 @@ public virtual bool Ignore([NotNull] Type type, ConfigurationSource configuratio
public virtual bool Ignore([NotNull] string name, ConfigurationSource configurationSource)
=> Ignore(new TypeIdentity(name), configurationSource);
- private bool Ignore(TypeIdentity type, ConfigurationSource configurationSource)
+ private bool Ignore(in TypeIdentity type, ConfigurationSource configurationSource)
{
var name = type.Name;
var ignoredConfigurationSource = Metadata.FindIgnoredTypeConfigurationSource(name);
diff --git a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs
index 5b13d8870f3..99adc494d68 100644
--- a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs
+++ b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs
@@ -148,7 +148,7 @@ public virtual bool HasField([CanBeNull] string fieldName, ConfigurationSource c
if (fieldName != null)
{
var fieldInfo = PropertyBase.GetFieldInfo(
- fieldName, Metadata.DeclaringType.ClrType, Metadata.Name,
+ fieldName, Metadata.DeclaringType, Metadata.Name,
shouldThrow: configurationSource == ConfigurationSource.Explicit);
Metadata.SetFieldInfo(fieldInfo, configurationSource);
return true;
diff --git a/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs
index 8c84747e565..351dedfcc4f 100644
--- a/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs
+++ b/src/EFCore/Metadata/Internal/InternalServicePropertyBuilder.cs
@@ -43,7 +43,7 @@ public virtual bool HasField([CanBeNull] string fieldName, ConfigurationSource c
if (fieldName != null)
{
var fieldInfo = PropertyBase.GetFieldInfo(
- fieldName, Metadata.DeclaringType.ClrType, Metadata.Name,
+ fieldName, Metadata.DeclaringType, Metadata.Name,
shouldThrow: configurationSource == ConfigurationSource.Explicit);
Metadata.SetFieldInfo(fieldInfo, configurationSource);
return true;
diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs
index f297f88764c..421187ee701 100644
--- a/src/EFCore/Metadata/Internal/Model.cs
+++ b/src/EFCore/Metadata/Internal/Model.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// 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 System;
@@ -23,8 +23,8 @@ public class Model : ConventionalAnnotatable, IMutableModel
private readonly SortedDictionary _entityTypes
= new SortedDictionary();
- private readonly Dictionary _clrTypeMap
- = new Dictionary();
+ private readonly Dictionary _clrTypeNameMap
+ = new Dictionary();
private readonly SortedDictionary> _entityTypesWithDefiningNavigation
= new SortedDictionary>();
@@ -109,8 +109,6 @@ public virtual EntityType AddEntityType(
var entityType = new EntityType(type, this, configurationSource);
- _clrTypeMap[type] = entityType;
-
return AddEntityType(entityType);
}
@@ -127,8 +125,6 @@ public virtual EntityType AddQueryType([NotNull] Type type)
IsQueryType = true
};
- _clrTypeMap[type] = queryType;
-
return AddEntityType(queryType);
}
@@ -188,9 +184,7 @@ public virtual EntityType GetOrAddEntityType([NotNull] string name)
/// directly from your code. This API may change or be removed in future releases.
///
public virtual EntityType FindEntityType([NotNull] Type type)
- => _clrTypeMap.TryGetValue(Check.NotNull(type, nameof(type)), out var entityType)
- ? entityType
- : FindEntityType(type.DisplayName());
+ => FindEntityType(GetDisplayName(type));
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -280,12 +274,6 @@ public virtual EntityType RemoveEntityType([CanBeNull] EntityType entityType)
{
var removed = _entityTypes.Remove(entityTypeName);
Debug.Assert(removed);
-
- if (entityType.ClrType != null)
- {
- removed = _clrTypeMap.Remove(entityType.ClrType);
- Debug.Assert(removed);
- }
}
entityType.OnTypeRemoved();
@@ -327,12 +315,27 @@ public virtual EntityType AddEntityType(
return AddEntityType(entityType);
}
+ ///
+ /// 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.
+ ///
+ public virtual string GetDisplayName(Type type)
+ {
+ if (!_clrTypeNameMap.TryGetValue(type, out var name))
+ {
+ name = type.DisplayName();
+ _clrTypeNameMap[type] = name;
+ }
+
+ return name;
+ }
+
///
/// 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.
///
public virtual bool HasEntityTypeWithDefiningNavigation([NotNull] Type clrType)
- => _entityTypesWithDefiningNavigation.ContainsKey(clrType.DisplayName());
+ => _entityTypesWithDefiningNavigation.ContainsKey(GetDisplayName(clrType));
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -349,7 +352,7 @@ public virtual EntityType FindEntityType(
[NotNull] Type type,
[NotNull] string definingNavigationName,
[NotNull] EntityType definingEntityType)
- => FindEntityType(type.DisplayName(), definingNavigationName, definingEntityType);
+ => FindEntityType(GetDisplayName(type), definingNavigationName, definingEntityType);
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -393,7 +396,7 @@ public virtual EntityType FindEntityType(
/// directly from your code. This API may change or be removed in future releases.
///
public virtual IReadOnlyCollection GetEntityTypes([NotNull] Type type)
- => GetEntityTypes(type.DisplayName());
+ => GetEntityTypes(GetDisplayName(type));
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -437,7 +440,7 @@ public virtual EntityType RemoveEntityType(
public virtual void Ignore(
[NotNull] Type type,
ConfigurationSource configurationSource = ConfigurationSource.Explicit)
- => Ignore(Check.NotNull(type, nameof(type)).DisplayName(), type, configurationSource);
+ => Ignore(GetDisplayName(Check.NotNull(type, nameof(type))), type, configurationSource);
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -473,7 +476,7 @@ private void Ignore(
{
Check.NotNull(type, nameof(type));
- return FindIgnoredTypeConfigurationSource(type.DisplayName());
+ return FindIgnoredTypeConfigurationSource(GetDisplayName(type));
}
///
@@ -492,7 +495,7 @@ private void Ignore(
public virtual void Unignore([NotNull] Type type)
{
Check.NotNull(type, nameof(type));
- Unignore(type.DisplayName());
+ Unignore(GetDisplayName(type));
}
///
diff --git a/src/EFCore/Metadata/Internal/ModelExtensions.cs b/src/EFCore/Metadata/Internal/ModelExtensions.cs
index 13cdf401682..1b15da449a3 100644
--- a/src/EFCore/Metadata/Internal/ModelExtensions.cs
+++ b/src/EFCore/Metadata/Internal/ModelExtensions.cs
@@ -58,7 +58,8 @@ public static bool ShouldBeOwnedType([NotNull] this IModel model, [NotNull] Type
while (clrType != null)
{
- if (ownedTypes.Contains(clrType.DisplayName()))
+ var name = (model as Model)?.GetDisplayName(clrType) ?? clrType.DisplayName();
+ if (ownedTypes.Contains(name))
{
return true;
}
@@ -89,7 +90,7 @@ public static void MarkAsOwnedType([NotNull] this Model model, [NotNull] string
/// directly from your code. This API may change or be removed in future releases.
///
public static void MarkAsOwnedType([NotNull] this Model model, [NotNull] Type clrType)
- => model.MarkAsOwnedType(clrType.DisplayName());
+ => model.MarkAsOwnedType(model.GetDisplayName(clrType));
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -114,7 +115,7 @@ public static void UnmarkAsOwnedType([NotNull] this Model model, [NotNull] Type
while (clrType != null)
{
- ownedTypes.Remove(clrType.DisplayName());
+ ownedTypes.Remove(model.GetDisplayName(clrType));
clrType = clrType.BaseType;
}
diff --git a/src/EFCore/Metadata/Internal/Navigation.cs b/src/EFCore/Metadata/Internal/Navigation.cs
index ae5f52a493b..5fd6a21a344 100644
--- a/src/EFCore/Metadata/Internal/Navigation.cs
+++ b/src/EFCore/Metadata/Internal/Navigation.cs
@@ -75,7 +75,10 @@ public virtual EntityType DeclaringEntityType
/// 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.
///
- public new virtual EntityType DeclaringType => DeclaringEntityType;
+ public override TypeBase DeclaringType
+ {
+ [DebuggerStepThrough] get => DeclaringEntityType;
+ }
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -217,8 +220,6 @@ public virtual IClrCollectionAccessor CollectionAccessor
IMutableForeignKey IMutableNavigation.ForeignKey => ForeignKey;
IEntityType INavigation.DeclaringEntityType => DeclaringEntityType;
IMutableEntityType IMutableNavigation.DeclaringEntityType => DeclaringEntityType;
- ITypeBase IPropertyBase.DeclaringType => DeclaringType;
- IMutableTypeBase IMutablePropertyBase.DeclaringType => DeclaringType;
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
diff --git a/src/EFCore/Metadata/Internal/Property.cs b/src/EFCore/Metadata/Internal/Property.cs
index 95c10cc0608..8f7c650e905 100644
--- a/src/EFCore/Metadata/Internal/Property.cs
+++ b/src/EFCore/Metadata/Internal/Property.cs
@@ -75,7 +75,7 @@ public Property(
/// 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.
///
- public new virtual EntityType DeclaringType
+ public override TypeBase DeclaringType
{
[DebuggerStepThrough] get => DeclaringEntityType;
}
@@ -465,9 +465,7 @@ public static string Format([NotNull] IEnumerable properties)
+ "}";
IEntityType IProperty.DeclaringEntityType => DeclaringEntityType;
- ITypeBase IPropertyBase.DeclaringType => DeclaringType;
IMutableEntityType IMutableProperty.DeclaringEntityType => DeclaringEntityType;
- IMutableTypeBase IMutablePropertyBase.DeclaringType => DeclaringType;
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -478,14 +476,13 @@ public static bool AreCompatible([NotNull] IReadOnlyList properties, [
Check.NotNull(properties, nameof(properties));
Check.NotNull(entityType, nameof(entityType));
- return properties.All(
- property =>
- property.IsShadowProperty
- || (entityType.HasClrType()
- && ((property.PropertyInfo != null
- && entityType.ClrType.GetRuntimeProperties().FirstOrDefault(p => p.Name == property.Name) != null)
- || (property.FieldInfo != null
- && entityType.ClrType.GetFieldInfo(property.Name) != null))));
+ return properties.All(property =>
+ property.IsShadowProperty
+ || (entityType.HasClrType()
+ && ((property.PropertyInfo != null
+ && entityType.GetRuntimeProperties().ContainsKey(property.Name))
+ || (property.FieldInfo != null
+ && entityType.GetRuntimeFields().ContainsKey(property.Name)))));
}
///
diff --git a/src/EFCore/Metadata/Internal/PropertyBase.cs b/src/EFCore/Metadata/Internal/PropertyBase.cs
index 8114576ddc5..a80f90e598a 100644
--- a/src/EFCore/Metadata/Internal/PropertyBase.cs
+++ b/src/EFCore/Metadata/Internal/PropertyBase.cs
@@ -51,10 +51,7 @@ protected PropertyBase(
/// 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.
///
- public virtual IMutableTypeBase DeclaringType
- {
- [DebuggerStepThrough] get => ((IMutablePropertyBase)this).DeclaringType;
- }
+ public abstract TypeBase DeclaringType { get; }
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -99,7 +96,7 @@ public virtual void SetField([CanBeNull] string fieldName, ConfigurationSource c
return;
}
- var fieldInfo = GetFieldInfo(fieldName, DeclaringType.ClrType, Name, shouldThrow: true);
+ var fieldInfo = GetFieldInfo(fieldName, DeclaringType, Name, shouldThrow: true);
if (fieldInfo != null)
{
SetFieldInfo(fieldInfo, configurationSource);
@@ -111,16 +108,15 @@ public virtual void SetField([CanBeNull] string fieldName, ConfigurationSource c
/// directly from your code. This API may change or be removed in future releases.
///
public static FieldInfo GetFieldInfo(
- [NotNull] string fieldName, [NotNull] Type type, [CanBeNull] string propertyName, bool shouldThrow)
+ [NotNull] string fieldName, [NotNull] TypeBase type, [CanBeNull] string propertyName, bool shouldThrow)
{
Debug.Assert(propertyName != null || !shouldThrow);
- var fieldInfo = type.GetFieldInfo(fieldName);
- if (fieldInfo == null
+ if (!type.GetRuntimeFields().TryGetValue(fieldName, out var fieldInfo)
&& shouldThrow)
{
throw new InvalidOperationException(
- CoreStrings.MissingBackingField(fieldName, propertyName, type.ShortDisplayName()));
+ CoreStrings.MissingBackingField(fieldName, propertyName, type.DisplayName()));
}
return fieldInfo;
@@ -276,5 +272,6 @@ public virtual PropertyAccessors Accessors
=> NonCapturingLazyInitializer.EnsureInitialized(ref _accessors, this, p => new PropertyAccessorsFactory().Create(p));
ITypeBase IPropertyBase.DeclaringType => DeclaringType;
+ IMutableTypeBase IMutablePropertyBase.DeclaringType => DeclaringType;
}
}
diff --git a/src/EFCore/Metadata/Internal/ServiceProperty.cs b/src/EFCore/Metadata/Internal/ServiceProperty.cs
index 7f63a4f6969..67653303baa 100644
--- a/src/EFCore/Metadata/Internal/ServiceProperty.cs
+++ b/src/EFCore/Metadata/Internal/ServiceProperty.cs
@@ -51,7 +51,10 @@ public ServiceProperty(
/// 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.
///
- public new virtual EntityType DeclaringType => DeclaringEntityType;
+ public override TypeBase DeclaringType
+ {
+ [DebuggerStepThrough] get => DeclaringEntityType;
+ }
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -136,7 +139,5 @@ public virtual DebugView DebugView
IEntityType IServiceProperty.DeclaringEntityType => DeclaringEntityType;
IMutableEntityType IMutableServiceProperty.DeclaringEntityType => DeclaringEntityType;
- ITypeBase IPropertyBase.DeclaringType => DeclaringType;
- IMutableTypeBase IMutablePropertyBase.DeclaringType => DeclaringType;
}
}
diff --git a/src/EFCore/Metadata/Internal/TypeBase.cs b/src/EFCore/Metadata/Internal/TypeBase.cs
index 2b3f9887c3e..d3d2552d254 100644
--- a/src/EFCore/Metadata/Internal/TypeBase.cs
+++ b/src/EFCore/Metadata/Internal/TypeBase.cs
@@ -5,8 +5,8 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Reflection;
using JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
namespace Microsoft.EntityFrameworkCore.Metadata.Internal
@@ -20,6 +20,9 @@ public abstract class TypeBase : ConventionalAnnotatable, IMutableTypeBase
private ConfigurationSource _configurationSource;
private readonly Dictionary _ignoredMembers = new Dictionary();
+ private Dictionary _runtimeProperties;
+ private Dictionary _runtimeFields;
+
///
/// 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.
@@ -42,7 +45,7 @@ protected TypeBase([NotNull] Type clrType, [NotNull] Model model, ConfigurationS
{
Check.NotNull(model, nameof(model));
- Name = clrType.DisplayName();
+ Name = model.GetDisplayName(clrType);
ClrType = clrType;
}
@@ -90,6 +93,37 @@ public virtual void UpdateConfigurationSource(ConfigurationSource configurationS
///
public abstract void PropertyMetadataChanged();
+ ///
+ /// 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.
+ ///
+ public Dictionary GetRuntimeProperties()
+ => ClrType == null
+ ? null
+ : (_runtimeProperties ??
+ (_runtimeProperties =
+ ClrType.GetRuntimeProperties().Where(p => !p.IsStatic()).ToDictionary(p => p.Name)));
+
+ ///
+ /// 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.
+ ///
+ public Dictionary GetRuntimeFields()
+ => ClrType == null
+ ? null
+ : (_runtimeFields ??
+ (_runtimeFields = ClrType.GetRuntimeFields().Where(f => !f.IsStatic).ToDictionary(p => p.Name)));
+
+ ///
+ /// 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.
+ ///
+ public virtual void ClearCaches()
+ {
+ _runtimeProperties = null;
+ _runtimeFields = null;
+ }
+
///
/// 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.
diff --git a/src/EFCore/Metadata/Internal/TypeIdentity.cs b/src/EFCore/Metadata/Internal/TypeIdentity.cs
index c939e8a3768..a4a95ad9ea5 100644
--- a/src/EFCore/Metadata/Internal/TypeIdentity.cs
+++ b/src/EFCore/Metadata/Internal/TypeIdentity.cs
@@ -4,7 +4,6 @@
using System;
using System.Diagnostics;
using JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Internal;
namespace Microsoft.EntityFrameworkCore.Metadata.Internal
{
@@ -15,16 +14,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public readonly struct TypeIdentity
{
- private readonly object _nameOrType;
-
///
/// 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.
///
[DebuggerStepThrough]
public TypeIdentity([NotNull] string name)
- : this((object)name)
{
+ Name = name;
+ Type = null;
}
///
@@ -32,34 +30,23 @@ public TypeIdentity([NotNull] string name)
/// directly from your code. This API may change or be removed in future releases.
///
[DebuggerStepThrough]
- public TypeIdentity([NotNull] Type type)
- : this((object)type)
- {
- }
-
- [DebuggerStepThrough]
- private TypeIdentity(object nameOrType)
+ public TypeIdentity([NotNull] Type type, [NotNull] Model model)
{
- _nameOrType = nameOrType;
+ Name = model.GetDisplayName(type);
+ Type = type;
}
///
/// 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.
///
- public string Name
- {
- [DebuggerStepThrough] get { return Type?.DisplayName() ?? (string)_nameOrType; }
- }
+ public string Name { [DebuggerStepThrough] get; }
///
/// 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.
///
- public Type Type
- {
- [DebuggerStepThrough] get { return _nameOrType as Type; }
- }
+ public Type Type { [DebuggerStepThrough] get; }
private string DebuggerDisplay() => Name;
}
diff --git a/src/EFCore/Storage/Internal/FallbackTypeMappingSource.cs b/src/EFCore/Storage/Internal/FallbackTypeMappingSource.cs
index 9a094d1c9a8..363e910c7fe 100644
--- a/src/EFCore/Storage/Internal/FallbackTypeMappingSource.cs
+++ b/src/EFCore/Storage/Internal/FallbackTypeMappingSource.cs
@@ -42,7 +42,7 @@ public FallbackTypeMappingSource(
/// 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.
///
- protected override CoreTypeMapping FindMapping(TypeMappingInfo mappingInfo)
+ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));
diff --git a/src/EFCore/Storage/TypeMappingInfo.cs b/src/EFCore/Storage/TypeMappingInfo.cs
index 79d001acd40..997b2b673cd 100644
--- a/src/EFCore/Storage/TypeMappingInfo.cs
+++ b/src/EFCore/Storage/TypeMappingInfo.cs
@@ -15,7 +15,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
///
/// Describes metadata needed to decide on a type mapping for a property or type.
///
- public readonly struct TypeMappingInfo
+ public readonly struct TypeMappingInfo : IEquatable
{
private readonly Type _providerClrType;
private readonly ValueConverter _customConverter;
@@ -153,7 +153,7 @@ public TypeMappingInfo(
///
/// The converter to apply.
/// The new mapping info.
- public TypeMappingInfo WithConverter(ValueConverterInfo converterInfo)
+ public TypeMappingInfo WithConverter(in ValueConverterInfo converterInfo)
=> new TypeMappingInfo(this, converterInfo);
///
diff --git a/src/EFCore/Storage/TypeMappingSource.cs b/src/EFCore/Storage/TypeMappingSource.cs
index 6d2d2bdf984..62c31afdfee 100644
--- a/src/EFCore/Storage/TypeMappingSource.cs
+++ b/src/EFCore/Storage/TypeMappingSource.cs
@@ -10,12 +10,14 @@
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
+#pragma warning disable 1574
+#pragma warning disable CS0419 // Ambiguous reference in cref attribute
namespace Microsoft.EntityFrameworkCore.Storage
{
///
///
/// The base class for non-relational type mapping starting with version 2.1. Non-relational providers
- /// should derive from this class and override
+ /// should derive from this class and override
///
///
/// This type is typically used by database providers (and other extensions). It is generally
@@ -37,7 +39,7 @@ protected TypeMappingSource([NotNull] TypeMappingSourceDependencies dependencies
}
private CoreTypeMapping FindMappingWithConversion(
- TypeMappingInfo mappingInfo,
+ in TypeMappingInfo mappingInfo,
[CanBeNull] IProperty property)
{
Check.NotNull(mappingInfo, nameof(mappingInfo));
@@ -58,13 +60,13 @@ private CoreTypeMapping 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)
{
@@ -72,7 +74,7 @@ private CoreTypeMapping FindMappingWithConversion(
.ValueConverterSelector
.Select(sourceType, providerClrType))
{
- var mappingInfoUsed = mappingInfo.WithConverter(converterInfo);
+ var mappingInfoUsed = k.WithConverter(converterInfo);
mapping = FindMapping(mappingInfoUsed);
if (mapping == null
diff --git a/src/EFCore/Storage/TypeMappingSourceBase.cs b/src/EFCore/Storage/TypeMappingSourceBase.cs
index 1a56e207be2..613f783206c 100644
--- a/src/EFCore/Storage/TypeMappingSourceBase.cs
+++ b/src/EFCore/Storage/TypeMappingSourceBase.cs
@@ -7,12 +7,14 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Utilities;
+#pragma warning disable 1574
+#pragma warning disable CS0419 // Ambiguous reference in cref attribute
namespace Microsoft.EntityFrameworkCore.Storage
{
///
///
/// The base class for non-relational type mapping starting with version 2.1. Non-relational providers
- /// should derive from this class and override
+ /// should derive from this class and override
///
///
/// This type is typically used by database providers (and other extensions). It is generally
@@ -49,7 +51,7 @@ protected TypeMappingSourceBase([NotNull] TypeMappingSourceDependencies dependen
///
/// The mapping info to use to create the mapping.
/// The type mapping, or null if none could be found.
- protected abstract CoreTypeMapping FindMapping(TypeMappingInfo mappingInfo);
+ protected abstract CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo);
///
/// Called after a mapping has been found so that it can be validated for the given property.
diff --git a/src/Shared/DictionaryExtensions.cs b/src/Shared/DictionaryExtensions.cs
index 771efc5c4e0..cc5b0c74daa 100644
--- a/src/Shared/DictionaryExtensions.cs
+++ b/src/Shared/DictionaryExtensions.cs
@@ -30,5 +30,14 @@ public static TValue GetOrAddNew(
}
return value;
}
+
+ ///
+ /// 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.
+ ///
+ public static TValue Find(
+ [NotNull] this IDictionary source,
+ [NotNull] TKey key)
+ => !source.TryGetValue(key, out var value) ? default : value;
}
}
diff --git a/src/Shared/PropertyInfoExtensions.cs b/src/Shared/PropertyInfoExtensions.cs
index e16258b1c04..5608235882f 100644
--- a/src/Shared/PropertyInfoExtensions.cs
+++ b/src/Shared/PropertyInfoExtensions.cs
@@ -18,11 +18,10 @@ public static bool IsStatic(this PropertyInfo property)
public static bool IsCandidateProperty(this PropertyInfo propertyInfo, bool needsWrite = true, bool publicOnly = true)
=> !propertyInfo.IsStatic()
- && propertyInfo.GetIndexParameters().Length == 0
&& propertyInfo.CanRead
&& (!needsWrite || propertyInfo.FindSetterProperty() != null)
- && propertyInfo.GetMethod != null && (!publicOnly || propertyInfo.GetMethod.IsPublic);
-
+ && propertyInfo.GetMethod != null && (!publicOnly || propertyInfo.GetMethod.IsPublic)
+ && propertyInfo.GetIndexParameters().Length == 0;
public static Type FindCandidateNavigationPropertyType(
this PropertyInfo propertyInfo,
diff --git a/test/EFCore.Relational.Tests/TestUtilities/TestRelationalTypeMappingSource.cs b/test/EFCore.Relational.Tests/TestUtilities/TestRelationalTypeMappingSource.cs
index 97e13b87039..01a8f0f8b9d 100644
--- a/test/EFCore.Relational.Tests/TestUtilities/TestRelationalTypeMappingSource.cs
+++ b/test/EFCore.Relational.Tests/TestUtilities/TestRelationalTypeMappingSource.cs
@@ -154,7 +154,7 @@ public TestStringTypeMapping(
}
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
{
var clrType = mappingInfo.ClrType;
var storeTypeName = mappingInfo.StoreTypeName;
diff --git a/test/EFCore.SqlServer.FunctionalTests/EverythingIsBytesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/EverythingIsBytesSqlServerTest.cs
index 9dd19c3b306..4bde591012c 100644
--- a/test/EFCore.SqlServer.FunctionalTests/EverythingIsBytesSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/EverythingIsBytesSqlServerTest.cs
@@ -222,7 +222,7 @@ public SqlServerBytesTypeMappingSource(
};
}
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
=> FindRawMapping(mappingInfo)?.Clone(mappingInfo);
private RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
diff --git a/test/EFCore.SqlServer.FunctionalTests/EverythingIsStringsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/EverythingIsStringsSqlServerTest.cs
index a83a1bdec08..15cf1d8ff02 100644
--- a/test/EFCore.SqlServer.FunctionalTests/EverythingIsStringsSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/EverythingIsStringsSqlServerTest.cs
@@ -243,7 +243,7 @@ public SqlServerStringsTypeMappingSource(
};
}
- protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
+ protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo)
=> FindRawMapping(mappingInfo)?.Clone(mappingInfo);
private RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
diff --git a/test/EFCore.Tests/Metadata/Conventions/Internal/NavigationAttributeConventionTest.cs b/test/EFCore.Tests/Metadata/Conventions/Internal/NavigationAttributeConventionTest.cs
index 073e46b1cbc..f637cf0793a 100644
--- a/test/EFCore.Tests/Metadata/Conventions/Internal/NavigationAttributeConventionTest.cs
+++ b/test/EFCore.Tests/Metadata/Conventions/Internal/NavigationAttributeConventionTest.cs
@@ -16,8 +16,8 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit;
-// ReSharper disable MemberHidesStaticFromOuterClass
+// ReSharper disable MemberHidesStaticFromOuterClass
// ReSharper disable InconsistentNaming
// ReSharper disable ClassNeverInstantiated.Local
// ReSharper disable UnusedMember.Local