public abstract IConventionIndex?OnIndexRemoved( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] IConventionIndex index);
/// <inheritdoc /> public virtual void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext <IConventionEntityTypeBuilder> context) => TryConfigurePrimaryKey(entityTypeBuilder);
private static void Process(IConventionEntityTypeBuilder entityTypeBuilder) { IConventionKey newKey = null; IConventionProperty idProperty = null; var entityType = entityTypeBuilder.Metadata; if (entityType.BaseType == null && entityType.IsDocumentRoot() && !entityType.IsKeyless) { idProperty = entityTypeBuilder.Property(typeof(string), IdPropertyName, setTypeConfigurationSource: false) ?.Metadata; if (idProperty != null) { if (idProperty.ClrType == typeof(string)) { idProperty.Builder.HasValueGenerator((_, __) => new IdValueGenerator()); } var partitionKey = entityType.GetPartitionKeyPropertyName(); if (partitionKey != null) { var partitionKeyProperty = entityType.FindProperty(partitionKey); if (partitionKeyProperty != null) { newKey = entityTypeBuilder.HasKey(new[] { idProperty, partitionKeyProperty })?.Metadata; } } else { newKey = entityTypeBuilder.HasKey(new[] { idProperty })?.Metadata; } } } else { idProperty = entityType.FindDeclaredProperty(IdPropertyName); } if (idProperty != null) { foreach (var key in idProperty.GetContainingKeys().ToList()) { if (key != newKey) { key.DeclaringEntityType.Builder.HasNoKey(key); } } } if (entityType.BaseType == null && !entityType.IsKeyless) { var jObjectProperty = entityTypeBuilder.Property(typeof(JObject), JObjectPropertyName); jObjectProperty.ToJsonProperty(""); jObjectProperty.ValueGenerated(ValueGenerated.OnAddOrUpdate); } else { var jObjectProperty = entityType.FindDeclaredProperty(JObjectPropertyName); if (jObjectProperty != null) { entityType.Builder.HasNoUnusedShadowProperties(new[] { jObjectProperty }); } } }
/// <summary> /// Discovers primary key candidates and configures the primary key if found. /// </summary> /// <param name="entityTypeBuilder"> The entity type builder. </param> protected virtual void TryConfigurePrimaryKey([NotNull] IConventionEntityTypeBuilder entityTypeBuilder) { var entityType = entityTypeBuilder.Metadata; if (entityType.BaseType != null || (entityType.IsKeyless && entityType.GetIsKeylessConfigurationSource() != ConfigurationSource.Convention) || !entityTypeBuilder.CanSetPrimaryKey(null)) { return; } List <IConventionProperty> keyProperties = null; var definingFk = entityType.FindDefiningNavigation()?.ForeignKey ?? entityType.FindOwnership(); if (definingFk != null && definingFk.DeclaringEntityType != entityType) { definingFk = null; } if (definingFk?.IsUnique == true) { keyProperties = definingFk.Properties.ToList(); } if (keyProperties == null) { var candidateProperties = entityType.GetProperties().Where( p => !p.IsShadowProperty() || !ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())); keyProperties = DiscoverKeyProperties(entityType, candidateProperties).ToList(); if (keyProperties.Count > 1) { Dependencies.Logger.MultiplePrimaryKeyCandidates(keyProperties[0], keyProperties[1]); return; } } if (definingFk?.IsUnique == false) { if (keyProperties.Count == 0 || definingFk.Properties.Contains(keyProperties.First())) { var primaryKey = entityType.FindPrimaryKey(); var shadowProperty = primaryKey?.Properties.Last(); if (shadowProperty == null || primaryKey.Properties.Count == 1 || definingFk.Properties.Contains(shadowProperty)) { shadowProperty = entityTypeBuilder.CreateUniqueProperty(typeof(int), "Id", required: true).Metadata; } keyProperties.Clear(); keyProperties.Add(shadowProperty); } var extraProperty = keyProperties[0]; keyProperties.RemoveAt(0); keyProperties.AddRange(definingFk.Properties); keyProperties.Add(extraProperty); } if (keyProperties.Count == 0) { var manyToManyForeignKeys = entityType.GetForeignKeys() .Where(fk => fk.GetReferencingSkipNavigations().Any(n => n.IsCollection)).ToList(); if (manyToManyForeignKeys.Count == 2) { keyProperties.AddRange(manyToManyForeignKeys.SelectMany(fk => fk.Properties)); } } ProcessKeyProperties(keyProperties, entityType); if (keyProperties.Count > 0) { entityTypeBuilder.PrimaryKey(keyProperties); } }
/// <summary> /// Called after an entity type is added to the model. /// </summary> /// <param name="entityTypeBuilder"> The builder for the entity type. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext <IConventionEntityTypeBuilder> context) { ProcessEntityType(entityTypeBuilder); }
private static void ProcessEntityType( IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext context) { var entityType = entityTypeBuilder.Metadata; var model = entityType.Model; var derivedTypesMap = (Dictionary <Type, List <IConventionEntityType> >?)model[CoreAnnotationNames.DerivedTypes]; if (derivedTypesMap == null) { derivedTypesMap = new Dictionary <Type, List <IConventionEntityType> >(); model.SetAnnotation(CoreAnnotationNames.DerivedTypes, derivedTypesMap); } var clrType = entityType.ClrType; var baseType = clrType.BaseType !; if (derivedTypesMap.TryGetValue(clrType, out var derivedTypes)) { foreach (var derivedType in derivedTypes) { if (!derivedType.IsOwned()) { derivedType.Builder.HasBaseType(entityType); } var otherBaseType = baseType; while (otherBaseType != typeof(object)) { if (derivedTypesMap.TryGetValue(otherBaseType, out var otherDerivedTypes)) { otherDerivedTypes.Remove(derivedType); } otherBaseType = otherBaseType.BaseType !; } } derivedTypesMap.Remove(clrType); } if (baseType == typeof(object)) { return; } IConventionEntityType?baseEntityType = null; while (baseEntityType == null && baseType != typeof(object) && baseType != null) { baseEntityType = model.FindEntityType(baseType); if (baseEntityType == null) { derivedTypesMap.GetOrAddNew(baseType).Add(entityType); } baseType = baseType.BaseType; } if (baseEntityType == null) { return; } if (!baseEntityType.HasSharedClrType && !baseEntityType.IsOwned()) { entityTypeBuilder.HasBaseType(baseEntityType); } }
/// <inheritdoc /> protected override void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, MySqlCharSetAttribute attribute, IConventionContext <IConventionEntityTypeBuilder> context) => entityTypeBuilder.HasCharSet(attribute.CharSetName, attribute.DelegationModes);
public abstract IConventionAnnotation?OnEntityTypeAnnotationChanged( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] string name, [CanBeNull] IConventionAnnotation?annotation, [CanBeNull] IConventionAnnotation?oldAnnotation);
public abstract IConventionEntityType?OnEntityTypeBaseTypeChanged( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] IConventionEntityType?newBaseType, [CanBeNull] IConventionEntityType?previousBaseType);
public abstract IConventionProperty?OnPropertyRemoved( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] IConventionProperty property);
public abstract IConventionEntityTypeBuilder?OnEntityTypeAdded([NotNull] IConventionEntityTypeBuilder entityTypeBuilder);
public abstract IConventionSkipNavigation?OnSkipNavigationRemoved( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] IConventionSkipNavigation navigation);
public abstract string?OnNavigationRemoved( [NotNull] IConventionEntityTypeBuilder sourceEntityTypeBuilder, [NotNull] IConventionEntityTypeBuilder targetEntityTypeBuilder, [NotNull] string navigationName, [CanBeNull] MemberInfo?memberInfo);
public abstract IConventionKey?OnKeyRemoved( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] IConventionKey key);
/// <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 IConventionKey OnPrimaryKeyChanged( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] IConventionKey newPrimaryKey, [CanBeNull] IConventionKey previousPrimaryKey) => _scope.OnEntityTypePrimaryKeyChanged(entityTypeBuilder, newPrimaryKey, previousPrimaryKey);
public abstract string?OnEntityTypeMemberIgnored( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] string name);
/// <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 IConventionEntityTypeBuilder OnEntityTypeAdded([NotNull] IConventionEntityTypeBuilder entityTypeBuilder) => _scope.OnEntityTypeAdded(entityTypeBuilder);
public abstract IConventionKey?OnEntityTypePrimaryKeyChanged( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] IConventionKey?newPrimaryKey, [CanBeNull] IConventionKey?previousPrimaryKey);
private static void SetDuplicateServiceProperties( IConventionEntityTypeBuilder entityTypeBuilder, Dictionary <Type, HashSet <MemberInfo> > duplicateServiceProperties) => entityTypeBuilder.HasAnnotation(CoreAnnotationNames.DuplicateServiceProperties, duplicateServiceProperties);
/// <inheritdoc /> public virtual void ProcessEntityTypeAnnotationChanged( IConventionEntityTypeBuilder entityTypeBuilder, string name, IConventionAnnotation?annotation, IConventionAnnotation?oldAnnotation, IConventionContext <IConventionAnnotation> context) { if (name == SqlServerAnnotationNames.IsTemporal) { if (annotation?.Value as bool? == true) { if (entityTypeBuilder.Metadata.GetTemporalPeriodStartPropertyName() == null) { entityTypeBuilder.HasPeriodStart(PeriodStartDefaultName); } if (entityTypeBuilder.Metadata.GetTemporalPeriodEndPropertyName() == null) { entityTypeBuilder.HasPeriodEnd(PeriodEndDefaultName); } } else { entityTypeBuilder.HasPeriodStart(null); entityTypeBuilder.HasPeriodEnd(null); } } if (name == SqlServerAnnotationNames.TemporalPeriodStartPropertyName || name == SqlServerAnnotationNames.TemporalPeriodEndPropertyName) { if (oldAnnotation?.Value is string oldPeriodPropertyName) { var oldPeriodProperty = entityTypeBuilder.Metadata.GetProperty(oldPeriodPropertyName); entityTypeBuilder.RemoveUnusedImplicitProperties(new[] { oldPeriodProperty }); if (oldPeriodProperty.GetTypeConfigurationSource() == ConfigurationSource.Explicit) { if ((name == SqlServerAnnotationNames.TemporalPeriodStartPropertyName && oldPeriodProperty.GetDefaultValue() is DateTime start && start == DateTime.MinValue) || (name == SqlServerAnnotationNames.TemporalPeriodEndPropertyName && oldPeriodProperty.GetDefaultValue() is DateTime end && end == DateTime.MaxValue)) { oldPeriodProperty.Builder.HasDefaultValue(null); } } } if (annotation?.Value is string periodPropertyName) { var periodPropertyBuilder = entityTypeBuilder.Property( typeof(DateTime), periodPropertyName); if (periodPropertyBuilder != null) { // set column name explicitly so that we don't try to uniquefy it to some other column // in case another property is defined that maps to the same column periodPropertyBuilder.HasColumnName(periodPropertyName); } } } }
private static void ProcessIdProperty(IConventionEntityTypeBuilder entityTypeBuilder) { IConventionKey newKey = null; IConventionProperty idProperty = null; var entityType = entityTypeBuilder.Metadata; if (entityType.BaseType == null && entityType.IsDocumentRoot() && !entityType.IsKeyless) { idProperty = entityType.FindDeclaredProperty(DefaultIdPropertyName) ?? entityType.GetDeclaredProperties().FirstOrDefault(p => p.GetJsonPropertyName() == IdPropertyJsonName) ?? entityTypeBuilder.Property(typeof(string), DefaultIdPropertyName, setTypeConfigurationSource: false) ?.ToJsonProperty(IdPropertyJsonName)?.Metadata; if (idProperty != null) { if (idProperty.ClrType == typeof(string)) { if (idProperty.IsPrimaryKey()) { idProperty.Builder.HasValueGenerator((Type)null); } else { idProperty.Builder.HasValueGenerator((_, __) => new IdValueGenerator()); } } var partitionKey = entityType.GetPartitionKeyPropertyName(); if (partitionKey != null) { var partitionKeyProperty = entityType.FindProperty(partitionKey); if (partitionKeyProperty == null) { newKey = entityTypeBuilder.HasKey(new[] { idProperty })?.Metadata; } else { if (entityType.FindKey(new[] { partitionKeyProperty, idProperty }) == null) { newKey = entityTypeBuilder.HasKey(new[] { idProperty, partitionKeyProperty })?.Metadata; } entityTypeBuilder.HasNoKey(new[] { idProperty }); } } else { newKey = entityTypeBuilder.HasKey(new[] { idProperty })?.Metadata; } } } else { idProperty = entityType.FindDeclaredProperty(DefaultIdPropertyName); } if (idProperty != null && idProperty.GetContainingKeys().Count() > (newKey == null ? 0 : 1)) { foreach (var key in idProperty.GetContainingKeys().ToList()) { if (key != newKey) { key.DeclaringEntityType.Builder.HasNoKey(key); } } } }
/// <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 string OnEntityTypeMemberIgnored( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] string name) => _scope.OnEntityTypeMemberIgnored(entityTypeBuilder, name);
public void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext <IConventionEntityTypeBuilder> context) { Applied = true; }
/// <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 IConventionEntityType OnEntityTypeBaseTypeChanged( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] IConventionEntityType newBaseType, [CanBeNull] IConventionEntityType previousBaseType) => _scope.OnEntityTypeBaseTypeChanged(entityTypeBuilder, newBaseType, previousBaseType);
private IConventionForeignKeyBuilder ConfigureInverseNavigation( IConventionEntityTypeBuilder entityTypeBuilder, MemberInfo navigationMemberInfo, IConventionEntityTypeBuilder targetEntityTypeBuilder, InversePropertyAttribute attribute) { var entityType = entityTypeBuilder.Metadata; var targetClrType = targetEntityTypeBuilder.Metadata.ClrType; var inverseNavigationPropertyInfo = targetEntityTypeBuilder.Metadata.GetRuntimeProperties().Values .FirstOrDefault(p => string.Equals(p.GetSimpleMemberName(), attribute.Property, StringComparison.OrdinalIgnoreCase)); if (inverseNavigationPropertyInfo == null || !Dependencies.MemberClassifier.FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo) .IsAssignableFrom(entityType.ClrType)) { throw new InvalidOperationException( CoreStrings.InvalidNavigationWithInverseProperty( navigationMemberInfo.Name, entityType.DisplayName(), attribute.Property, targetClrType.ShortDisplayName())); } if (Equals(inverseNavigationPropertyInfo, navigationMemberInfo)) { throw new InvalidOperationException( CoreStrings.SelfReferencingNavigationWithInverseProperty( navigationMemberInfo.Name, entityType.DisplayName(), navigationMemberInfo.Name, entityType.DisplayName())); } // Check for InversePropertyAttribute on the inverse navigation to verify that it matches. if (Attribute.IsDefined(inverseNavigationPropertyInfo, typeof(InversePropertyAttribute))) { var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute <InversePropertyAttribute>(true); if (inverseAttribute.Property != navigationMemberInfo.GetSimpleMemberName()) { throw new InvalidOperationException( CoreStrings.InversePropertyMismatch( navigationMemberInfo.Name, entityType.DisplayName(), inverseNavigationPropertyInfo.Name, targetEntityTypeBuilder.Metadata.DisplayName())); } } var referencingNavigationsWithAttribute = AddInverseNavigation(entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo); var ambiguousInverse = FindAmbiguousInverse( navigationMemberInfo, entityType, referencingNavigationsWithAttribute); var baseType = targetEntityTypeBuilder.Metadata.BaseType; while (ambiguousInverse == null && baseType != null) { var navigationMap = GetInverseNavigations(baseType); if (navigationMap != null && navigationMap.TryGetValue(inverseNavigationPropertyInfo.Name, out var inverseTuple)) { referencingNavigationsWithAttribute = inverseTuple.References; ambiguousInverse = FindAmbiguousInverse(navigationMemberInfo, entityType, referencingNavigationsWithAttribute); } baseType = baseType.BaseType; } if (ambiguousInverse != null) { var existingInverse = targetEntityTypeBuilder.Metadata.FindNavigation(inverseNavigationPropertyInfo)?.Inverse; var existingInverseType = existingInverse?.DeclaringEntityType; if (existingInverse != null && IsAmbiguousInverse( existingInverse.GetIdentifyingMemberInfo(), existingInverseType, referencingNavigationsWithAttribute)) { var fk = existingInverse.ForeignKey; if (fk.IsOwnership || fk.DeclaringEntityType.Builder.HasNoRelationship(fk, fromDataAnnotation: true) == null) { fk.Builder.HasNavigation( (string)null, existingInverse.IsOnDependent, fromDataAnnotation: true); } } var existingNavigation = entityType.FindNavigation(navigationMemberInfo); if (existingNavigation != null) { var fk = existingNavigation.ForeignKey; if (fk.IsOwnership || fk.DeclaringEntityType.Builder.HasNoRelationship(fk, fromDataAnnotation: true) == null) { fk.Builder.HasNavigation( (string)null, existingNavigation.IsOnDependent, fromDataAnnotation: true); } } var existingAmbiguousNavigation = FindActualEntityType(ambiguousInverse.Value.Item2) .FindNavigation(ambiguousInverse.Value.Item1); if (existingAmbiguousNavigation != null) { var fk = existingAmbiguousNavigation.ForeignKey; if (fk.IsOwnership || fk.DeclaringEntityType.Builder.HasNoRelationship(fk, fromDataAnnotation: true) == null) { fk.Builder.HasNavigation( (string)null, existingAmbiguousNavigation.IsOnDependent, fromDataAnnotation: true); } } return(entityType.FindNavigation(navigationMemberInfo)?.ForeignKey.Builder); } var ownership = entityType.FindOwnership(); if (ownership != null && ownership.PrincipalEntityType == targetEntityTypeBuilder.Metadata && ownership.PrincipalToDependent?.GetIdentifyingMemberInfo() != inverseNavigationPropertyInfo) { Dependencies.Logger.NonOwnershipInverseNavigationWarning( entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo, ownership.PrincipalToDependent?.GetIdentifyingMemberInfo()); return(null); } if (entityType.DefiningEntityType != null && entityType.DefiningEntityType == targetEntityTypeBuilder.Metadata && entityType.DefiningNavigationName != inverseNavigationPropertyInfo.GetSimpleMemberName()) { Dependencies.Logger.NonDefiningInverseNavigationWarning( entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo, entityType.DefiningEntityType.GetRuntimeProperties()[entityType.DefiningNavigationName]); return(null); } return(entityType.Model.FindIsOwnedConfigurationSource(entityType.ClrType) != null && !entityType.IsInOwnershipPath(targetEntityTypeBuilder.Metadata) ? targetEntityTypeBuilder.HasOwnership( entityTypeBuilder.Metadata.ClrType, inverseNavigationPropertyInfo, navigationMemberInfo, fromDataAnnotation: true) : targetEntityTypeBuilder.HasRelationship( entityType, inverseNavigationPropertyInfo, navigationMemberInfo, fromDataAnnotation: true)); }
/// <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> /// Discovers primary key candidates and configures the primary key if found. /// </summary> /// <param name="entityTypeBuilder">The entity type builder.</param> protected virtual void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entityTypeBuilder) { var entityType = entityTypeBuilder.Metadata; if (entityType.BaseType != null || (entityType.IsKeyless && entityType.GetIsKeylessConfigurationSource() != ConfigurationSource.Convention) || !entityTypeBuilder.CanSetPrimaryKey(null)) { return; } List <IConventionProperty>?keyProperties = null; var ownership = entityType.FindOwnership(); if (ownership != null && ownership.DeclaringEntityType != entityType) { ownership = null; } if (ownership?.IsUnique == true) { keyProperties = ownership.Properties.ToList(); } if (keyProperties == null) { var candidateProperties = entityType.GetProperties().Where( p => !p.IsImplicitlyCreated() || !ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())); keyProperties = DiscoverKeyProperties(entityType, candidateProperties).ToList(); if (keyProperties.Count > 1) { Dependencies.Logger.MultiplePrimaryKeyCandidates(keyProperties[0], keyProperties[1]); return; } } if (ownership?.IsUnique == false) { if (keyProperties.Count == 0 || ownership.Properties.Contains(keyProperties.First())) { var primaryKey = entityType.FindPrimaryKey(); var shadowProperty = primaryKey?.Properties.Last(); if (shadowProperty == null || primaryKey !.Properties.Count == 1 || ownership.Properties.Contains(shadowProperty)) { shadowProperty = entityTypeBuilder.CreateUniqueProperty(typeof(int), "Id", required: true) !.Metadata; } keyProperties.Clear(); keyProperties.Add(shadowProperty); } var extraProperty = keyProperties[0]; keyProperties.RemoveAt(0); keyProperties.AddRange(ownership.Properties); keyProperties.Add(extraProperty); } if (keyProperties.Count == 0) { var manyToManyForeignKeys = entityType.GetForeignKeys() .Where(fk => fk.GetReferencingSkipNavigations().Any(n => n.IsCollection)).ToList(); if (manyToManyForeignKeys.Count == 2 && !manyToManyForeignKeys.Any(fk => fk.PrincipalEntityType == entityType)) { keyProperties.AddRange(manyToManyForeignKeys.SelectMany(fk => fk.Properties)); } } for (var i = keyProperties.Count - 1; i >= 0; i--) { var property = keyProperties[i]; for (var j = i - 1; j >= 0; j--) { if (property == keyProperties[j]) { keyProperties.RemoveAt(j); i--; } } } ProcessKeyProperties(keyProperties, entityType); if (keyProperties.Count > 0) { entityTypeBuilder.PrimaryKey(keyProperties); } }
/// <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 IConventionKey OnKeyRemoved([NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] IConventionKey key) => _scope.OnKeyRemoved(entityTypeBuilder, key);
/// <summary> /// Called after an entity type is added to the model if it has an attribute. /// </summary> /// <param name="entityTypeBuilder"> The builder for the entity type. </param> /// <param name="attribute"> The attribute. </param> /// <param name="context"> Additional information associated with convention execution. </param> protected abstract void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, TAttribute attribute, IConventionContext <IConventionEntityTypeBuilder> context);
/// <inheritdoc /> public virtual void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext <IConventionEntityTypeBuilder> context) => CheckIndexAttributesAndEnsureIndex(entityTypeBuilder.Metadata, shouldThrow: false);