/// <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 IConventionForeignKey OnSkipNavigationForeignKeyChanged( [NotNull] IConventionSkipNavigationBuilder navigationBuilder, [NotNull] IConventionForeignKey foreignKey, [NotNull] IConventionForeignKey oldForeignKey) => _scope.OnSkipNavigationForeignKeyChanged(navigationBuilder, foreignKey, oldForeignKey);
/// <inheritdoc /> IMetadataReference <IConventionForeignKey> IConventionBatch.Track(IConventionForeignKey foreignKey) => _dispatcher.Tracker.Track(foreignKey);
/// <summary> /// Gets the <see cref="ConfigurationSource" /> for the constraint name. /// </summary> /// <param name="foreignKey"> The foreign key. </param> /// <returns> The <see cref="ConfigurationSource" /> for the constraint name. </returns> public static ConfigurationSource?GetConstraintNameConfigurationSource([NotNull] this IConventionForeignKey foreignKey) => foreignKey.FindAnnotation(RelationalAnnotationNames.Name) ?.GetConfigurationSource();
/// <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 IConventionForeignKey OnForeignKeyRemoved( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] IConventionForeignKey foreignKey) => _scope.OnForeignKeyRemoved(entityTypeBuilder, foreignKey);
/// <summary> /// Sets the foreign key constraint name. /// </summary> /// <param name="foreignKey"> The foreign key. </param> /// <param name="value"> The value to set. </param> /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> public static void SetConstraintName( [NotNull] this IConventionForeignKey foreignKey, [CanBeNull] string value, bool fromDataAnnotation = false) => foreignKey.SetOrRemoveAnnotation( RelationalAnnotationNames.Name, Check.NullButNotEmpty(value, nameof(value)), fromDataAnnotation);
private static string GetPropertyBaseName(IConventionForeignKey foreignKey) => foreignKey.DependentToPrincipal?.Name ?? foreignKey.PrincipalEntityType.ShortName();
private bool TryFindMatchingProperties( IConventionForeignKey foreignKey, string baseName, bool onDependent, bool matchPk, out IReadOnlyList <IConventionProperty> match) { match = null; var dependentEntityType = onDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; var principalEntityType = onDependent ? foreignKey.PrincipalEntityType : foreignKey.DeclaringEntityType; var propertiesToReference = onDependent ? foreignKey.PrincipalKey.Properties : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties; if (propertiesToReference == null) { return(false); } var foreignKeyProperties = new IConventionProperty[propertiesToReference.Count]; var matchFound = true; for (var i = 0; i < propertiesToReference.Count; i++) { var referencedProperty = propertiesToReference[i]; var property = TryGetProperty( dependentEntityType, baseName, referencedProperty.Name); if (property == null) { matchFound = false; continue; } foreignKeyProperties[i] = property; } if (!matchFound && propertiesToReference.Count == 1 && baseName.Length > 0) { var property = TryGetProperty( dependentEntityType, baseName, "Id"); if (property != null) { foreignKeyProperties[0] = property; matchFound = true; } } if (!matchFound) { return(false); } if (!ForeignKey.AreCompatible( propertiesToReference, foreignKeyProperties, principalEntityType, dependentEntityType, shouldThrow: false)) { if (propertiesToReference.All( p => !p.IsShadowProperty() || p.GetConfigurationSource().Overrides(ConfigurationSource.DataAnnotation))) { Dependencies.Logger.IncompatibleMatchingForeignKeyProperties(foreignKeyProperties, propertiesToReference); } // Stop searching if match found, but is incompatible return(true); } foreach (var key in dependentEntityType.GetKeys()) { var isKeyContainedInForeignKey = true; // ReSharper disable once LoopCanBeConvertedToQuery // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < key.Properties.Count; i++) { if (!foreignKeyProperties.Contains(key.Properties[i])) { isKeyContainedInForeignKey = false; break; } } if (isKeyContainedInForeignKey && (!foreignKey.IsUnique || (key.IsPrimaryKey() && !matchPk))) { // Stop searching if match found, but is incompatible return(true); } } match = foreignKeyProperties; return(true); }
private IConventionRelationshipBuilder ReuniquifyTemporaryProperties(IConventionForeignKey foreignKey, bool force) => ((ForeignKey)foreignKey).Builder.ReuniquifyTemporaryProperties(force);
/// <summary> /// Returns the delete behavior to set for the given foreign key. /// </summary> /// <param name="foreignKey">The foreign key.</param> protected virtual DeleteBehavior GetTargetDeleteBehavior(IConventionForeignKey foreignKey) => foreignKey.IsRequired ? DeleteBehavior.Cascade : DeleteBehavior.ClientSetNull;