コード例 #1
0
        private IConventionForeignKey CreateSkipNavigationForeignKey(
            IConventionSkipNavigation skipNavigation,
            IConventionEntityTypeBuilder joinEntityTypeBuilder,
            IConventionProperty partitionKeyProperty)
        {
            if (skipNavigation.ForeignKey != null &&
                !skipNavigation.Builder.CanSetForeignKey(null))
            {
                return(skipNavigation.ForeignKey);
            }

            var principalKey = skipNavigation.DeclaringEntityType.FindPrimaryKey();

            if (principalKey == null ||
                principalKey.Properties.All(p => p.Name != partitionKeyProperty.Name))
            {
                return(CreateSkipNavigationForeignKey(skipNavigation, joinEntityTypeBuilder));
            }

            if (skipNavigation.ForeignKey?.Properties.Contains(partitionKeyProperty) == true)
            {
                return(skipNavigation.ForeignKey);
            }

            var dependentProperties = new IConventionProperty[principalKey.Properties.Count];

            for (var i = 0; i < principalKey.Properties.Count; i++)
            {
                var principalProperty = principalKey.Properties[i];
                if (principalProperty.Name == partitionKeyProperty.Name)
                {
                    dependentProperties[i] = partitionKeyProperty;
                }
                else
                {
                    dependentProperties[i] = joinEntityTypeBuilder.CreateUniqueProperty(
                        principalProperty.ClrType, principalProperty.Name, required: true) !.Metadata;
                }
            }

            var foreignKey = joinEntityTypeBuilder.HasRelationship(skipNavigation.DeclaringEntityType, dependentProperties, principalKey) !
                             .IsUnique(false) !
                             .Metadata;

            skipNavigation.Builder.HasForeignKey(foreignKey);

            return(foreignKey);
        }
コード例 #2
0
        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 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);
            }
        }
コード例 #3
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([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);
            }
        }