Esempio n. 1
0
        /// <summary>
        ///     Generates a unique name for the new joint entity type.
        /// </summary>
        /// <param name="skipNavigation">The target skip navigation.</param>
        /// <returns>A unique entity type name.</returns>
        protected virtual string GenerateJoinTypeName(IConventionSkipNavigation skipNavigation)
        {
            var inverseSkipNavigation = skipNavigation.Inverse;

            Check.DebugAssert(
                inverseSkipNavigation?.Inverse == skipNavigation,
                "Inverse's inverse should be the original skip navigation");

            var declaringEntityType = skipNavigation.DeclaringEntityType;
            var inverseEntityType   = inverseSkipNavigation.DeclaringEntityType;
            var model = declaringEntityType.Model;
            var joinEntityTypeName = declaringEntityType.ShortName();
            var inverseName        = inverseEntityType.ShortName();

            joinEntityTypeName = StringComparer.Ordinal.Compare(joinEntityTypeName, inverseName) < 0
                ? joinEntityTypeName + inverseName
                : inverseName + joinEntityTypeName;

            if (model.FindEntityType(joinEntityTypeName) != null)
            {
                var otherIdentifiers = model.GetEntityTypes().ToDictionary(et => et.Name, _ => 0);
                joinEntityTypeName = Uniquifier.Uniquify(
                    joinEntityTypeName,
                    otherIdentifiers,
                    int.MaxValue);
            }

            return(joinEntityTypeName);
        }
Esempio n. 2
0
        private void CreateJoinEntityType(IConventionSkipNavigationBuilder skipNavigationBuilder)
        {
            var skipNavigation = (SkipNavigation)skipNavigationBuilder.Metadata;

            if (skipNavigation.ForeignKey != null ||
                !skipNavigation.IsCollection)
            {
                return;
            }

            var inverseSkipNavigation = skipNavigation.Inverse;

            if (inverseSkipNavigation == null ||
                inverseSkipNavigation.ForeignKey != null ||
                !inverseSkipNavigation.IsCollection)
            {
                return;
            }

            Check.DebugAssert(inverseSkipNavigation.Inverse == skipNavigation,
                              "Inverse's inverse should be the original skip navigation");

            var declaringEntityType = skipNavigation.DeclaringEntityType;
            var inverseEntityType   = inverseSkipNavigation.DeclaringEntityType;
            var model = declaringEntityType.Model;

            var joinEntityTypeName = declaringEntityType.ShortName() + inverseEntityType.ShortName();

            if (model.FindEntityType(joinEntityTypeName) != null)
            {
                var otherIdentifiers = model.GetEntityTypes().ToDictionary(et => et.Name, et => 0);
                joinEntityTypeName = Uniquifier.Uniquify(
                    joinEntityTypeName,
                    otherIdentifiers,
                    int.MaxValue);
            }

            var joinEntityTypeBuilder = model.Builder.SharedTypeEntity(
                joinEntityTypeName, Model.DefaultPropertyBagType, ConfigurationSource.Convention);

            var leftForeignKey = CreateSkipNavigationForeignKey(skipNavigation, joinEntityTypeBuilder);

            if (leftForeignKey == null)
            {
                model.Builder.HasNoEntityType(joinEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            var rightForeignKey = CreateSkipNavigationForeignKey(inverseSkipNavigation, joinEntityTypeBuilder);

            if (rightForeignKey == null)
            {
                model.Builder.HasNoEntityType(joinEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            skipNavigation.Builder.HasForeignKey(leftForeignKey, ConfigurationSource.Convention);
            inverseSkipNavigation.Builder.HasForeignKey(rightForeignKey, ConfigurationSource.Convention);
        }
        /// <inheritdoc />
        public virtual void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext <IConventionModelBuilder> context)
        {
            var model          = modelBuilder.Metadata;
            var modelSequences =
                (SortedDictionary <(string Name, string Schema), Sequence>)model[RelationalAnnotationNames.Sequences];

            if (modelSequences != null)
            {
                var maxLength = model.GetMaxIdentifierLength();
                var toReplace = modelSequences
                                .Where(s => s.Key.Name.Length > maxLength).ToList();

                foreach (var sequence in toReplace)
                {
                    var schemaName      = sequence.Key.Schema;
                    var newSequenceName = Uniquifier.Uniquify(
                        sequence.Key.Name, modelSequences,
                        sequenceName => (sequenceName, schemaName), maxLength);
                    Sequence.SetName((IMutableModel)model, sequence.Value, newSequenceName);
                }
            }
        }
Esempio n. 4
0
        private static ForeignKey CreateSkipNavigationForeignKey(
            SkipNavigation skipNavigation,
            InternalEntityTypeBuilder associationEntityTypeBuilder)
        {
            var principalEntityType = skipNavigation.DeclaringEntityType;
            var principalKey        = principalEntityType.FindPrimaryKey();

            if (principalKey == null)
            {
                return(null);
            }

            var dependentEndForeignKeyPropertyNames = new List <string>();
            var otherIdentifiers = associationEntityTypeBuilder.Metadata
                                   .GetDeclaredProperties().ToDictionary(p => p.Name, p => 0);

            foreach (var property in principalKey.Properties)
            {
                var propertyName = Uniquifier.Uniquify(
                    string.Format(
                        AssociationPropertyNameTemplate,
                        principalEntityType.ShortName(),
                        property.Name),
                    otherIdentifiers,
                    int.MaxValue);
                dependentEndForeignKeyPropertyNames.Add(propertyName);
                otherIdentifiers.Add(propertyName, 0);
            }

            return(associationEntityTypeBuilder
                   .HasRelationship(
                       principalEntityType.Name,
                       dependentEndForeignKeyPropertyNames,
                       principalKey,
                       ConfigurationSource.Convention)
                   .IsUnique(false, ConfigurationSource.Convention)
                   .Metadata);
        }
Esempio n. 5
0
        private void CreateAssociationEntityType(
            IConventionSkipNavigationBuilder skipNavigationBuilder)
        {
            var skipNavigation = (SkipNavigation)skipNavigationBuilder.Metadata;

            if (skipNavigation.AssociationEntityType != null)
            {
                return;
            }

            if (skipNavigation.ForeignKey != null ||
                skipNavigation.TargetEntityType == skipNavigation.DeclaringEntityType ||
                !skipNavigation.IsCollection)
            {
                // do not create the association entity type for a self-referencing
                // skip navigation, or for one that is already "in use"
                // (i.e. has its Foreign Key assigned).
                return;
            }

            var inverseSkipNavigation = skipNavigation.Inverse;

            if (inverseSkipNavigation == null ||
                inverseSkipNavigation.ForeignKey != null ||
                !inverseSkipNavigation.IsCollection)
            {
                // do not create the association entity type if
                // the inverse skip navigation is already "in use"
                // (i.e. has its Foreign Key assigned).
                return;
            }

            Check.DebugAssert(inverseSkipNavigation.Inverse == skipNavigation,
                              "Inverse's inverse should be the original skip navigation");

            var declaringEntityType = skipNavigation.DeclaringEntityType;
            var inverseEntityType   = inverseSkipNavigation.DeclaringEntityType;
            var model = declaringEntityType.Model;

            // create the association entity type
            var associationEntityTypeName = string.Format(
                AssociationEntityTypeNameTemplate,
                declaringEntityType.ShortName(),
                inverseEntityType.ShortName());

            if (model.FindEntityType(associationEntityTypeName) != null)
            {
                var otherIdentifiers = model.GetEntityTypes().ToDictionary(et => et.Name, et => 0);
                associationEntityTypeName = Uniquifier.Uniquify(
                    associationEntityTypeName,
                    otherIdentifiers,
                    int.MaxValue);
            }

            var associationEntityTypeBuilder = model.Builder.SharedEntity(
                associationEntityTypeName, Model.DefaultPropertyBagType, ConfigurationSource.Convention);

            // Create left and right foreign keys from the outer entity types to
            // the association entity type and configure the skip navigations.
            // Roll back if any of this fails.
            var leftForeignKey =
                CreateSkipNavigationForeignKey(skipNavigation, associationEntityTypeBuilder);

            if (leftForeignKey == null)
            {
                model.Builder.HasNoEntityType(
                    associationEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            var rightForeignKey =
                CreateSkipNavigationForeignKey(inverseSkipNavigation, associationEntityTypeBuilder);

            if (rightForeignKey == null)
            {
                // Removing the association entity type will also remove
                // the leftForeignKey created above.
                model.Builder.HasNoEntityType(
                    associationEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            skipNavigation.Builder.HasForeignKey(leftForeignKey, ConfigurationSource.Convention);
            inverseSkipNavigation.Builder.HasForeignKey(rightForeignKey, ConfigurationSource.Convention);

            // Creating the primary key below also negates the need for an index on
            // the properties of leftForeignKey - that index is automatically removed.
            associationEntityTypeBuilder.PrimaryKey(
                leftForeignKey.Properties.Concat(rightForeignKey.Properties).ToList(),
                ConfigurationSource.Convention);
        }