public abstract IConventionIndex?OnIndexRemoved(
     [NotNull] IConventionEntityTypeBuilder entityTypeBuilder,
     [NotNull] IConventionIndex index);
示例#2
0
 /// <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);
 }
示例#6
0
        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);
            }
        }
示例#7
0
 /// <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);
示例#15
0
 /// <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);
示例#17
0
 /// <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);
                    }
                }
            }
        }
示例#21
0
        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);
                    }
                }
            }
        }
示例#22
0
 /// <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;
 }
示例#24
0
 /// <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);
示例#25
0
        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));
        }
示例#26
0
 /// <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);
示例#27
0
        /// <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);
            }
        }
示例#28
0
 /// <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);
示例#30
0
 /// <inheritdoc />
 public virtual void ProcessEntityTypeAdded(
     IConventionEntityTypeBuilder entityTypeBuilder,
     IConventionContext <IConventionEntityTypeBuilder> context)
 => CheckIndexAttributesAndEnsureIndex(entityTypeBuilder.Metadata, shouldThrow: false);