diff --git a/src/EFCore/Extensions/ConventionModelExtensions.cs b/src/EFCore/Extensions/ConventionModelExtensions.cs index 392115faece..6a2061d3937 100644 --- a/src/EFCore/Extensions/ConventionModelExtensions.cs +++ b/src/EFCore/Extensions/ConventionModelExtensions.cs @@ -24,7 +24,7 @@ public static class ConventionModelExtensions /// The type to find the corresponding entity type for. /// The entity type, or if none if found. public static IConventionEntityType FindEntityType([NotNull] this IConventionModel model, [NotNull] Type type) - => (IConventionEntityType)((IModel)model).FindEntityType(type); + => ((Model)model).FindEntityType(type); /// /// Gets the entity type for the given name, defining navigation name diff --git a/src/EFCore/Extensions/ModelExtensions.cs b/src/EFCore/Extensions/ModelExtensions.cs index 90386515e27..ecd6bad495c 100644 --- a/src/EFCore/Extensions/ModelExtensions.cs +++ b/src/EFCore/Extensions/ModelExtensions.cs @@ -30,7 +30,7 @@ public static class ModelExtensions /// The entity type, or if none if found. [DebuggerStepThrough] public static IEntityType FindEntityType([NotNull] this IModel model, [NotNull] Type type) - => ((Model)Check.NotNull(model, nameof(model))).FindEntityType(Check.NotNull(type, nameof(type))); + => ((Model)model).FindEntityType(Check.NotNull(type, nameof(type))); /// /// Gets the entity that maps the given entity class, where the class may be a proxy derived from the @@ -87,7 +87,7 @@ public static IEntityType FindEntityType( /// The entity types found. [DebuggerStepThrough] public static IReadOnlyCollection GetEntityTypes([NotNull] this IModel model, [NotNull] Type type) - => model.AsModel().GetEntityTypes(type); + => ((Model)model).GetEntityTypes(type); /// /// Gets the entity types matching the given name. @@ -97,7 +97,7 @@ public static IReadOnlyCollection GetEntityTypes([NotNull] this IMo /// The entity types found. [DebuggerStepThrough] public static IReadOnlyCollection GetEntityTypes([NotNull] this IModel model, [NotNull] string name) - => model.AsModel().GetEntityTypes(name); + => ((Model)model).GetEntityTypes(name); /// /// Gets a value indicating whether the model contains a corresponding entity type with a defining navigation. diff --git a/src/EFCore/Extensions/MutableModelExtensions.cs b/src/EFCore/Extensions/MutableModelExtensions.cs index 51e7383c44e..24371118172 100644 --- a/src/EFCore/Extensions/MutableModelExtensions.cs +++ b/src/EFCore/Extensions/MutableModelExtensions.cs @@ -26,7 +26,7 @@ public static class MutableModelExtensions /// The type to find the corresponding entity type for. /// The entity type, or if none if found. public static IMutableEntityType FindEntityType([NotNull] this IMutableModel model, [NotNull] Type type) - => (IMutableEntityType)((IModel)model).FindEntityType(type); + => ((Model)model).FindEntityType(type); /// /// Gets the entity type for the given name, defining navigation name diff --git a/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs index 24261c47c78..a7cd632ed2d 100644 --- a/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs @@ -38,27 +38,26 @@ public virtual void ProcessEntityTypeAdded( if (clrType == null || entityType.HasSharedClrType || entityType.HasDefiningNavigation() - || entityType.FindDeclaredOwnership() != null - || entityType.Model.FindIsOwnedConfigurationSource(clrType) != null) + || entityType.Model.FindIsOwnedConfigurationSource(clrType) != null + || entityType.FindOwnership() != null) { return; } var model = entityType.Model; - var directlyDerivedTypes = model.GetEntityTypes().Where( - t => t != entityType - && t.HasClrType() - && !t.HasDefiningNavigation() - && t.FindDeclaredOwnership() == null - && model.FindIsOwnedConfigurationSource(t.ClrType) == null - && ((t.BaseType == null && clrType.IsAssignableFrom(t.ClrType)) - || (t.BaseType == entityType.BaseType && FindClosestBaseType(t) == entityType)) - && !t.HasSharedClrType) - .ToList(); - - foreach (var directlyDerivedType in directlyDerivedTypes) + foreach (var directlyDerivedType in model.GetEntityTypes()) { - directlyDerivedType.Builder.HasBaseType(entityType); + if (directlyDerivedType != entityType + && directlyDerivedType.HasClrType() + && !directlyDerivedType.HasSharedClrType + && !directlyDerivedType.HasDefiningNavigation() + && model.FindIsOwnedConfigurationSource(directlyDerivedType.ClrType) == null + && directlyDerivedType.FindDeclaredOwnership() == null + && ((directlyDerivedType.BaseType == null && clrType.IsAssignableFrom(directlyDerivedType.ClrType)) + || (directlyDerivedType.BaseType == entityType.BaseType && FindClosestBaseType(directlyDerivedType) == entityType))) + { + directlyDerivedType.Builder.HasBaseType(entityType); + } } } } diff --git a/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs b/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs index 037edd439ea..bc25a3b36bd 100644 --- a/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { @@ -33,18 +32,14 @@ protected InheritanceDiscoveryConventionBase([NotNull] ProviderConventionSetBuil /// The entity type. protected virtual IConventionEntityType FindClosestBaseType([NotNull] IConventionEntityType entityType) { - Check.NotNull(entityType, nameof(entityType)); - - var clrType = entityType.ClrType; - Check.NotNull(clrType, nameof(entityType.ClrType)); - - var baseType = clrType.BaseType; + var baseType = entityType.ClrType.BaseType; + var model = entityType.Model; IConventionEntityType baseEntityType = null; - while (baseType != null - && baseEntityType == null) + && baseEntityType == null + && baseType != typeof(object)) { - baseEntityType = entityType.Model.FindEntityType(baseType); + baseEntityType = model.FindEntityType(baseType); baseType = baseType.BaseType; } diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index 47ea1f077af..0d43c6489cd 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -1151,7 +1151,17 @@ public virtual ForeignKey FindForeignKey( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual ForeignKey FindOwnership() - => GetForeignKeys().FirstOrDefault(fk => fk.IsOwnership); + { + foreach (var foreignKey in GetForeignKeys()) + { + if (foreignKey.IsOwnership) + { + return foreignKey; + } + } + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -1160,7 +1170,17 @@ public virtual ForeignKey FindOwnership() /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual ForeignKey FindDeclaredOwnership() - => GetDeclaredForeignKeys().FirstOrDefault(fk => fk.IsOwnership); + { + foreach (var foreignKey in _foreignKeys) + { + if (foreignKey.IsOwnership) + { + return foreignKey; + } + } + + return null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -1180,7 +1200,7 @@ public virtual IEnumerable GetDeclaredForeignKeys() public virtual IEnumerable GetDerivedForeignKeys() => _directlyDerivedTypes.Count == 0 ? Enumerable.Empty() - : GetDerivedTypes().SelectMany(et => et.GetDeclaredForeignKeys()); + : GetDerivedTypes().SelectMany(et => et._foreignKeys); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index e5274c68234..dcf73d493cc 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -285,9 +285,12 @@ public virtual EntityType FindEntityType([NotNull] Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual EntityType FindEntityType([NotNull] string name) - => _entityTypes.TryGetValue(Check.NotEmpty(name, nameof(name)), out var entityType) + { + Check.DebugAssert(!string.IsNullOrEmpty(name), "name is null or empty"); + return _entityTypes.TryGetValue(name, out var entityType) ? entityType : null; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to