/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual bool Apply(InternalModelBuilder modelBuilder, EntityType type) { if (type.HasDefiningNavigation()) { var entityTypes = modelBuilder.Metadata.GetEntityTypes(type.Name); var otherEntityType = entityTypes.FirstOrDefault(); if (otherEntityType?.HasDefiningNavigation() == true) { var ownership = otherEntityType.FindOwnership(); if (ownership != null && entityTypes.Count == 1) { using (modelBuilder.Metadata.ConventionDispatcher.StartBatch()) { var detachedRelationship = InternalEntityTypeBuilder.DetachRelationship(ownership); var weakSnapshot = InternalEntityTypeBuilder.DetachAllMembers(otherEntityType); modelBuilder.RemoveEntityType(otherEntityType, ConfigurationSource.Explicit); detachedRelationship.WeakEntityTypeSnapshot = weakSnapshot; detachedRelationship.Attach(ownership.PrincipalEntityType.Builder); } } } } return(true); }
/// <summary> /// Called after an entity type is removed from the model. /// </summary> /// <param name="modelBuilder"> The builder for the model. </param> /// <param name="entityType"> The removed entity type. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessEntityTypeRemoved( IConventionModelBuilder modelBuilder, IConventionEntityType entityType, IConventionContext <IConventionEntityType> context) { if (!entityType.HasDefiningNavigation()) { return; } var entityTypes = modelBuilder.Metadata.GetEntityTypes(entityType.Name); var otherEntityType = entityTypes.FirstOrDefault(); if (otherEntityType?.HasDefiningNavigation() == true && entityTypes.Count == 1 && otherEntityType.FindOwnership() is ForeignKey ownership) { using (context.DelayConventions()) { InternalEntityTypeBuilder.DetachRelationship(ownership).Attach(ownership.PrincipalEntityType.Builder); } } }
private InternalRelationshipBuilder ReuniquifyTemporaryProperties(ForeignKey foreignKey, bool force) { if (!force && (foreignKey.GetForeignKeyPropertiesConfigurationSource() != null || !foreignKey.DeclaringEntityType.Builder.ShouldReuniquifyTemporaryProperties( foreignKey.Properties, foreignKey.PrincipalKey.Properties, foreignKey.IsRequired && foreignKey.GetIsRequiredConfigurationSource().Overrides(ConfigurationSource.Convention), GetPropertyBaseName(foreignKey)))) { return(foreignKey.Builder); } var relationshipBuilder = foreignKey.Builder; using (var batch = foreignKey.DeclaringEntityType.Model.ConventionDispatcher.StartBatch()) { var temporaryProperties = foreignKey.Properties.Where( p => p.IsShadowProperty && ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())).ToList(); var keysToDetach = temporaryProperties.SelectMany( p => p.GetContainingKeys() .Where(k => ConfigurationSource.Convention.Overrides(k.GetConfigurationSource()))) .Distinct().ToList(); List <RelationshipSnapshot> detachedRelationships = null; foreach (var key in keysToDetach) { foreach (var referencingForeignKey in key.GetReferencingForeignKeys().ToList()) { if (detachedRelationships == null) { detachedRelationships = new List <RelationshipSnapshot>(); } detachedRelationships.Add(InternalEntityTypeBuilder.DetachRelationship(referencingForeignKey)); } } var detachedKeys = InternalEntityTypeBuilder.DetachKeys(keysToDetach); var detachedIndexes = InternalEntityTypeBuilder.DetachIndexes( temporaryProperties.SelectMany(p => p.GetContainingIndexes()).Distinct()); relationshipBuilder = relationshipBuilder.HasForeignKey((IReadOnlyList <Property>)null, ConfigurationSource.Convention); if (detachedIndexes != null) { foreach (var indexBuilderTuple in detachedIndexes) { indexBuilderTuple.Attach(indexBuilderTuple.Metadata.DeclaringEntityType.Builder); } } if (detachedKeys != null) { foreach (var detachedKeyTuple in detachedKeys) { detachedKeyTuple.Item1.Attach(foreignKey.DeclaringEntityType.RootType().Builder, detachedKeyTuple.Item2); } } if (detachedRelationships != null) { foreach (var detachedRelationship in detachedRelationships) { detachedRelationship.Attach(); } } return(batch.Run(relationshipBuilder)); } }