public abstract bool?OnForeignKeyRequirednessChanged( IConventionForeignKeyBuilder relationshipBuilder);
/// <summary> /// Called after the principal end of a foreign key is changed. /// </summary> /// <param name="relationshipBuilder">The builder for the foreign key.</param> /// <param name="context">Additional information associated with convention execution.</param> public virtual void ProcessForeignKeyPrincipalEndChanged( IConventionForeignKeyBuilder relationshipBuilder, IConventionContext <IConventionForeignKeyBuilder> context) => ProcessForeignKeyAdded(relationshipBuilder, context);
public abstract bool?OnForeignKeyDependentRequirednessChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder);
public OnForeignKeyPrincipalEndChangedNode(IConventionForeignKeyBuilder relationshipBuilder) { RelationshipBuilder = relationshipBuilder; }
/// <summary> /// Returns a value indicating whether the foreign key constraint name can be set for this relationship /// from the current configuration source /// </summary> /// <param name="relationship"> The builder being used to configure the relationship. </param> /// <param name="name"> The name of the foreign key constraint. </param> /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> /// <returns> <see langword="true" /> if the configuration can be applied. </returns> public static bool CanSetConstraintName( [NotNull] this IConventionForeignKeyBuilder relationship, [CanBeNull] string name, bool fromDataAnnotation = false) => Check.NotNull(relationship, nameof(relationship)) .CanSetAnnotation(RelationalAnnotationNames.Name, name, fromDataAnnotation);
public OnForeignKeyAddedNode(IConventionForeignKeyBuilder relationshipBuilder) { RelationshipBuilder = relationshipBuilder; }
public OnForeignKeyDependentRequirednessChangedNode(IConventionForeignKeyBuilder relationshipBuilder) { RelationshipBuilder = relationshipBuilder; }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual bool?OnForeignKeyRequirednessChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder) => _scope.OnForeignKeyRequirednessChanged(relationshipBuilder);
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual bool?OnForeignKeyOwnershipChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder) => _scope.OnForeignKeyOwnershipChanged(relationshipBuilder);
public abstract IConventionForeignKeyBuilder?OnForeignKeyPrincipalEndChanged( IConventionForeignKeyBuilder relationshipBuilder);
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual IConventionForeignKeyBuilder OnForeignKeyAdded([NotNull] IConventionForeignKeyBuilder relationshipBuilder) => _scope.OnForeignKeyAdded(relationshipBuilder);
public abstract bool?OnForeignKeyOwnershipChanged( IConventionForeignKeyBuilder relationshipBuilder);
public abstract IConventionAnnotation?OnForeignKeyAnnotationChanged( IConventionForeignKeyBuilder relationshipBuilder, string name, IConventionAnnotation?annotation, IConventionAnnotation?oldAnnotation);
public abstract IConventionForeignKeyBuilder?OnForeignKeyAdded(IConventionForeignKeyBuilder relationshipBuilder);
public override bool?OnForeignKeyOwnershipChanged( IConventionForeignKeyBuilder relationshipBuilder) { Add(new OnForeignKeyOwnershipChangedNode(relationshipBuilder)); return(relationshipBuilder.Metadata.IsOwnership); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual IConventionForeignKeyBuilder OnForeignKeyPrincipalEndChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder) => _scope.OnForeignKeyPrincipalEndChanged(relationshipBuilder);
public override IConventionForeignKeyBuilder OnForeignKeyPrincipalEndChanged( IConventionForeignKeyBuilder relationshipBuilder) { Add(new OnForeignKeyPrincipalEndChangedNode(relationshipBuilder)); return(relationshipBuilder); }
/// <inheritdoc /> public virtual void ProcessForeignKeyOwnershipChanged( IConventionForeignKeyBuilder relationshipBuilder, IConventionContext <bool?> context) => TryConfigurePrimaryKey(relationshipBuilder.Metadata.DeclaringEntityType.Builder);
public OnForeignKeyUniquenessChangedNode(IConventionForeignKeyBuilder relationshipBuilder) { RelationshipBuilder = relationshipBuilder; }
/// <summary> /// Returns a value indicating whether the foreign key constraint name can be set for this relationship /// from the current configuration source /// </summary> /// <remarks> /// See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see> for more information and examples. /// </remarks> /// <param name="relationship">The builder being used to configure the relationship.</param> /// <param name="name">The name of the foreign key constraint.</param> /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param> /// <returns><see langword="true" /> if the configuration can be applied.</returns> public static bool CanSetConstraintName( this IConventionForeignKeyBuilder relationship, string?name, bool fromDataAnnotation = false) => relationship.CanSetAnnotation(RelationalAnnotationNames.Name, name, fromDataAnnotation);
public OnForeignKeyOwnershipChangedNode(IConventionForeignKeyBuilder relationshipBuilder) { RelationshipBuilder = relationshipBuilder; }
/// <inheritdoc /> public virtual void ProcessForeignKeyOwnershipChanged( IConventionForeignKeyBuilder relationshipBuilder, IConventionContext <bool?> context) { ProcessIdProperty(relationshipBuilder.Metadata.DeclaringEntityType.Builder); }
/// <summary> /// Called after the principal end of a foreign key is changed. /// </summary> /// <param name="relationshipBuilder"> The builder for the foreign key. </param> /// <param name="dependentToPrincipalAttributes"> The attributes on the dependent to principal navigation. </param> /// <param name="principalToDependentAttributes"> The attributes on the principal to dependent navigation. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessForeignKeyPrincipalEndChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder, [CanBeNull] IEnumerable<TAttribute> dependentToPrincipalAttributes, [CanBeNull] IEnumerable<TAttribute> principalToDependentAttributes, [NotNull] IConventionContext<IConventionForeignKeyBuilder> context) => throw new NotImplementedException();
public override IConventionForeignKeyBuilder OnForeignKeyAdded(IConventionForeignKeyBuilder relationshipBuilder) { Add(new OnForeignKeyAddedNode(relationshipBuilder)); return(relationshipBuilder); }
private IConventionForeignKeyBuilder?DiscoverProperties( IConventionForeignKeyBuilder relationshipBuilder, IConventionContext context) { var foreignKey = relationshipBuilder.Metadata; var foreignKeyProperties = FindCandidateForeignKeyProperties(relationshipBuilder.Metadata, onDependent: true); var propertiesConfigurationSource = foreignKey.GetPropertiesConfigurationSource(); if (!ConfigurationSource.Convention.OverridesStrictly(propertiesConfigurationSource) && (propertiesConfigurationSource != ConfigurationSource.Convention || (foreignKey.Properties.All(p => !p.IsImplicitlyCreated()) && (foreignKeyProperties == null || !foreignKey.Properties.SequenceEqual(foreignKeyProperties))))) { var batch = context.DelayConventions(); using var foreignKeyReference = batch.Track(foreignKey); foreach (var fkProperty in foreignKey.Properties) { if (ConfigurationSource.Convention.Overrides(fkProperty.GetTypeConfigurationSource()) && (fkProperty.IsShadowProperty() || fkProperty.IsIndexerProperty()) && fkProperty.ClrType.IsNullableType() == foreignKey.IsRequired && fkProperty.GetContainingForeignKeys().All(otherFk => otherFk.IsRequired == foreignKey.IsRequired)) { var newType = fkProperty.ClrType.MakeNullable(!foreignKey.IsRequired); if (fkProperty.ClrType != newType) { fkProperty.DeclaringEntityType.Builder.Property( newType, fkProperty.Name, fkProperty.GetConfigurationSource() == ConfigurationSource.DataAnnotation); } } } batch.Dispose(); return(foreignKeyReference.Object is null || !foreignKeyReference.Object.IsInModel ? null : foreignKeyReference.Object.Builder); } var invertible = true; if (foreignKey.IsOwnership || foreignKey.DeclaringEntityType.IsKeyless || (!foreignKey.IsUnique && !ConfigurationSource.Convention.Overrides(foreignKey.GetIsUniqueConfigurationSource())) || foreignKey.PrincipalToDependent?.IsCollection == true || foreignKey.DeclaringEntityType.FindOwnership() != null || (foreignKey.IsBaseLinking() && foreignKey.PrincipalEntityType.IsAssignableFrom(foreignKey.DeclaringEntityType))) { relationshipBuilder = relationshipBuilder.HasEntityTypes( foreignKey.PrincipalEntityType, foreignKey.DeclaringEntityType) !; invertible = false; } else if (ConfigurationSource.Convention.Overrides(foreignKey.GetPrincipalEndConfigurationSource()) && (foreignKey.PrincipalEntityType.FindOwnership() != null && foreignKey.PrincipalToDependent != null && foreignKey.DependentToPrincipal == null)) { var invertedRelationshipBuilder = relationshipBuilder.HasEntityTypes( foreignKey.DeclaringEntityType, foreignKey.PrincipalEntityType); if (invertedRelationshipBuilder != null) { return(invertedRelationshipBuilder); } } if (foreignKeyProperties == null) { if (invertible && ConfigurationSource.Convention.Overrides(foreignKey.GetPrincipalEndConfigurationSource())) { var candidatePropertiesOnPrincipal = FindCandidateForeignKeyProperties(foreignKey, onDependent: false); if (candidatePropertiesOnPrincipal != null) { var invertedRelationshipBuilder = relationshipBuilder .HasEntityTypes(foreignKey.DeclaringEntityType, foreignKey.PrincipalEntityType); if (invertedRelationshipBuilder is not null && invertedRelationshipBuilder.Metadata is IConventionForeignKey invertedFk && invertedFk.IsSelfReferencing()) { invertedRelationshipBuilder = invertedRelationshipBuilder.HasNavigations( invertedFk.PrincipalToDependent?.Name, invertedFk.DependentToPrincipal?.Name); } return(invertedRelationshipBuilder ?? (!foreignKey.IsInModel ? null : relationshipBuilder)); } } if (foreignKey.DeclaringEntityType.BaseType == null && !foreignKey.IsSelfReferencing()) { if (foreignKey.IsUnique) { // Try to use PK properties if principal end is not ambiguous if (!foreignKey.IsOwnership && (!ConfigurationSource.Convention.Overrides(foreignKey.GetPrincipalEndConfigurationSource()) || foreignKey.DeclaringEntityType.IsInOwnershipPath(foreignKey.PrincipalEntityType))) { foreignKeyProperties = GetCompatiblePrimaryKeyProperties( foreignKey.DeclaringEntityType, foreignKey.PrincipalEntityType, foreignKey.PrincipalKey.Properties); } else if (invertible) { foreignKeyProperties = FindCandidateForeignKeyProperties(foreignKey, onDependent: true, matchPk: true); var candidatePropertiesOnPrincipal = FindCandidateForeignKeyProperties(foreignKey, onDependent: false, matchPk: true); if (candidatePropertiesOnPrincipal != null) { if (foreignKeyProperties == null) { using var batch = context.DelayConventions(); var invertedRelationshipBuilder = relationshipBuilder .HasEntityTypes(foreignKey.DeclaringEntityType, foreignKey.PrincipalEntityType) !; return(batch.Run( invertedRelationshipBuilder.HasForeignKey(candidatePropertiesOnPrincipal) !.Metadata) ?.Builder); } foreignKeyProperties = null; ((ForeignKey)relationshipBuilder.Metadata).SetPrincipalEndConfigurationSource(null); } } } else { // Try match properties with the exact name as principal key if they are a proper subset of the dependent PK var dependentPk = foreignKey.DeclaringEntityType.FindPrimaryKey(); if (dependentPk != null && dependentPk.Properties.Count > foreignKey.PrincipalKey.Properties.Count && TryFindMatchingProperties(foreignKey, "", onDependent: true, matchPk: false, out foreignKeyProperties) && foreignKeyProperties != null && foreignKeyProperties.Any( p => !dependentPk.Properties.Contains(p) || p.Name.Equals("Id", StringComparison.OrdinalIgnoreCase))) { foreignKeyProperties = null; } } } if (foreignKeyProperties == null && invertible && ConfigurationSource.Convention.Overrides(foreignKey.GetPrincipalEndConfigurationSource())) { ((ForeignKey)relationshipBuilder.Metadata).SetPrincipalEndConfigurationSource(null); } } else if (invertible && ConfigurationSource.Convention.Overrides(foreignKey.GetPrincipalEndConfigurationSource())) { var candidatePropertiesOnPrincipal = FindCandidateForeignKeyProperties(foreignKey, onDependent: false); if (candidatePropertiesOnPrincipal != null) { // Principal end is ambiguous foreignKeyProperties = null; ((ForeignKey)relationshipBuilder.Metadata).SetPrincipalEndConfigurationSource(null); } } if (foreignKeyProperties == null) { return(((ForeignKey)foreignKey).Builder.ReuniquifyImplicitProperties(false)); } var conflictingFKCount = foreignKey.DeclaringEntityType.FindForeignKeys(foreignKeyProperties) .Concat( foreignKey.DeclaringEntityType.GetDerivedTypes() .SelectMany(et => et.FindDeclaredForeignKeys(foreignKeyProperties))) .Count(); if (foreignKey.Properties.SequenceEqual(foreignKeyProperties)) { return(conflictingFKCount > 1 ? ((ForeignKey)foreignKey).Builder.ReuniquifyImplicitProperties(true) : relationshipBuilder); } if (conflictingFKCount > 0) { return(((ForeignKey)foreignKey).Builder.ReuniquifyImplicitProperties(false)); } var newRelationshipBuilder = relationshipBuilder.HasForeignKey(foreignKeyProperties); if (newRelationshipBuilder != null) { return(newRelationshipBuilder); } return(relationshipBuilder.Metadata.IsInModel ? relationshipBuilder : null); }
public override bool?OnForeignKeyUniquenessChanged( IConventionForeignKeyBuilder relationshipBuilder) { Add(new OnForeignKeyUniquenessChangedNode(relationshipBuilder)); return(relationshipBuilder.Metadata.IsUnique); }
private IConventionForeignKeyBuilder?UpdateRelationshipBuilder( IConventionForeignKeyBuilder relationshipBuilder, IConventionContext context) { var foreignKey = relationshipBuilder.Metadata; var fkPropertyOnPrincipal = FindForeignKeyAttributeOnProperty(foreignKey.PrincipalEntityType, foreignKey.PrincipalToDependent?.Name); var fkPropertyOnDependent = FindForeignKeyAttributeOnProperty(foreignKey.DeclaringEntityType, foreignKey.DependentToPrincipal?.Name); if (fkPropertyOnDependent != null && fkPropertyOnPrincipal != null) { Dependencies.Logger.ForeignKeyAttributesOnBothPropertiesWarning( foreignKey.PrincipalToDependent !, foreignKey.DependentToPrincipal !, fkPropertyOnPrincipal, fkPropertyOnDependent); var newBuilder = SplitNavigationsToSeparateRelationships(relationshipBuilder); if (newBuilder is null) { context.StopProcessing(); return(null); } relationshipBuilder = newBuilder; fkPropertyOnPrincipal = null; } var fkPropertiesOnPrincipalToDependent = FindCandidateDependentPropertiesThroughNavigation(relationshipBuilder, pointsToPrincipal: false); var fkPropertiesOnDependentToPrincipal = FindCandidateDependentPropertiesThroughNavigation(relationshipBuilder, pointsToPrincipal: true); if (fkPropertiesOnDependentToPrincipal != null && fkPropertiesOnPrincipalToDependent != null) { Dependencies.Logger.ForeignKeyAttributesOnBothNavigationsWarning( relationshipBuilder.Metadata.DependentToPrincipal !, relationshipBuilder.Metadata.PrincipalToDependent !); var newBuilder = SplitNavigationsToSeparateRelationships(relationshipBuilder); if (newBuilder is null) { context.StopProcessing(); return(null); } relationshipBuilder = newBuilder; fkPropertiesOnPrincipalToDependent = null; } var fkPropertiesOnNavigation = fkPropertiesOnDependentToPrincipal ?? fkPropertiesOnPrincipalToDependent; var upgradePrincipalToDependentNavigationSource = fkPropertiesOnPrincipalToDependent != null; var upgradeDependentToPrincipalNavigationSource = fkPropertiesOnDependentToPrincipal != null; var shouldInvert = false; IReadOnlyList <string> fkPropertiesToSet; if (fkPropertiesOnNavigation == null || fkPropertiesOnNavigation.Count == 0) { if (fkPropertyOnDependent == null && fkPropertyOnPrincipal == null) { return(null); } if (fkPropertyOnDependent != null) { fkPropertiesToSet = new List <string> { fkPropertyOnDependent.GetSimpleMemberName() }; upgradeDependentToPrincipalNavigationSource = true; } else { if (foreignKey.PrincipalToDependent !.IsCollection) { context.StopProcessing(); return(null); } shouldInvert = true; fkPropertiesToSet = new List <string> { fkPropertyOnPrincipal !.GetSimpleMemberName() }; upgradePrincipalToDependentNavigationSource = true; } } else { fkPropertiesToSet = fkPropertiesOnNavigation; if (fkPropertyOnDependent == null && fkPropertyOnPrincipal == null) { if (fkPropertiesOnPrincipalToDependent != null && foreignKey.IsUnique) { shouldInvert = true; } } else { var fkProperty = fkPropertyOnDependent ?? fkPropertyOnPrincipal; if (fkPropertiesOnNavigation.Count != 1 || !Equals(fkPropertiesOnNavigation.First(), fkProperty !.GetSimpleMemberName())) { Dependencies.Logger.ConflictingForeignKeyAttributesOnNavigationAndPropertyWarning( fkPropertiesOnDependentToPrincipal != null ? relationshipBuilder.Metadata.DependentToPrincipal ! : relationshipBuilder.Metadata.PrincipalToDependent !, fkProperty !); var newBuilder = SplitNavigationsToSeparateRelationships(relationshipBuilder); if (newBuilder is null) { context.StopProcessing(); return(null); } relationshipBuilder = newBuilder; upgradePrincipalToDependentNavigationSource = false; fkPropertiesToSet = fkPropertiesOnDependentToPrincipal ?? new List <string> { fkPropertyOnDependent !.GetSimpleMemberName() }; } if (fkPropertyOnDependent != null || fkPropertiesOnDependentToPrincipal != null) { upgradeDependentToPrincipalNavigationSource = true; } else { shouldInvert = true; } } } var newRelationshipBuilder = relationshipBuilder; if (upgradeDependentToPrincipalNavigationSource) { newRelationshipBuilder = newRelationshipBuilder.HasNavigation( newRelationshipBuilder.Metadata.DependentToPrincipal !.Name, pointsToPrincipal: true, fromDataAnnotation: true) !; } if (upgradePrincipalToDependentNavigationSource) { newRelationshipBuilder = newRelationshipBuilder.HasNavigation( newRelationshipBuilder.Metadata.PrincipalToDependent !.Name, pointsToPrincipal: false, fromDataAnnotation: true) !; } if (shouldInvert) { newRelationshipBuilder = newRelationshipBuilder.HasEntityTypes( foreignKey.DeclaringEntityType, foreignKey.PrincipalEntityType, fromDataAnnotation: true) !; } else { var existingProperties = foreignKey.DeclaringEntityType.FindProperties(fkPropertiesToSet); if (existingProperties != null) { var conflictingFk = foreignKey.DeclaringEntityType.FindForeignKeys(existingProperties) .FirstOrDefault( fk => fk != foreignKey && fk.PrincipalEntityType == foreignKey.PrincipalEntityType && fk.GetConfigurationSource() == ConfigurationSource.DataAnnotation && fk.GetPropertiesConfigurationSource() == ConfigurationSource.DataAnnotation); if (conflictingFk != null) { throw new InvalidOperationException( CoreStrings.ConflictingForeignKeyAttributes( existingProperties.Format(), foreignKey.DeclaringEntityType.DisplayName(), foreignKey.PrincipalEntityType.DisplayName())); } } } return(newRelationshipBuilder.HasForeignKey(fkPropertiesToSet, fromDataAnnotation: true)); }
public override bool?OnForeignKeyDependentRequirednessChanged( IConventionForeignKeyBuilder relationshipBuilder) { Add(new OnForeignKeyDependentRequirednessChangedNode(relationshipBuilder)); return(relationshipBuilder.Metadata.IsRequiredDependent); }
public abstract bool?OnForeignKeyUniquenessChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder);
public abstract IReadOnlyList <IConventionProperty>?OnForeignKeyPropertiesChanged( IConventionForeignKeyBuilder relationshipBuilder, IReadOnlyList <IConventionProperty> oldDependentProperties, IConventionKey oldPrincipalKey);