Пример #1
0
        protected virtual IEnumerable <MigrationOperation> Add(IForeignKey target, ModelDifferContext diffContext)
        {
            var targetExtensions                    = MetadataExtensions.Extensions(target);
            var declaringRootEntityType             = target.DeclaringEntityType.RootType();
            var targetEntityTypeExtensions          = MetadataExtensions.Extensions(declaringRootEntityType);
            var targetPrincipalEntityTypeExtensions = MetadataExtensions.Extensions(target.PrincipalEntityType.RootType());

            // TODO: Set OnDelete (See #1084)
            var operation = new AddForeignKeyOperation
            {
                Schema            = targetEntityTypeExtensions.Schema,
                Table             = targetEntityTypeExtensions.Table,
                Name              = targetExtensions.Name,
                Columns           = GetColumnNames(target.Properties),
                ReferencedSchema  = targetPrincipalEntityTypeExtensions.Schema,
                ReferencedTable   = targetPrincipalEntityTypeExtensions.Table,
                ReferencedColumns = GetColumnNames(target.PrincipalKey.Properties)
            };

            CopyAnnotations(Annotations.For(target), operation);

            var createTableOperation = diffContext.FindCreate(declaringRootEntityType);

            if (createTableOperation != null)
            {
                createTableOperation.ForeignKeys.Add(operation);
            }
            else
            {
                yield return(operation);
            }
        }
Пример #2
0
        protected virtual IEnumerable <MigrationOperation> Add(IEntityType target, ModelDifferContext diffContext)
        {
            var targetExtensions = MetadataExtensions.Extensions(target);

            var createTableOperation = new CreateTableOperation
            {
                Schema = targetExtensions.Schema,
                Name   = targetExtensions.Table
            };

            CopyAnnotations(Annotations.For(target), createTableOperation);

            createTableOperation.Columns.AddRange(target.GetPropertiesInHierarchy().SelectMany(p => Add(p, inline: true)).Cast <AddColumnOperation>());
            var primaryKey = target.GetPrimaryKey();

            createTableOperation.PrimaryKey = Add(primaryKey).Cast <AddPrimaryKeyOperation>().Single();
            createTableOperation.UniqueConstraints.AddRange(
                target.GetKeys().Where(k => k != primaryKey).SelectMany(Add).Cast <AddUniqueConstraintOperation>());

            diffContext.AddCreate(target, createTableOperation);

            yield return(createTableOperation);

            foreach (var operation in target.GetIndexesInHierarchy().SelectMany(Add))
            {
                yield return(operation);
            }
        }
Пример #3
0
        protected virtual IEnumerable <MigrationOperation> Diff(
            IEntityType source,
            IEntityType target,
            ModelDifferContext diffContext)
        {
            var sourceExtensions = MetadataExtensions.Extensions(source);
            var targetExtensions = MetadataExtensions.Extensions(target);

            var schemaChanged = sourceExtensions.Schema != targetExtensions.Schema;
            var renamed       = sourceExtensions.Table != targetExtensions.Table;

            if (schemaChanged || renamed)
            {
                yield return(new RenameTableOperation
                {
                    Schema = sourceExtensions.Schema,
                    Name = sourceExtensions.Table,
                    NewSchema = schemaChanged ? targetExtensions.Schema : null,
                    NewName = renamed ? targetExtensions.Table : null
                });
            }

            diffContext.AddMapping(source, target);

            var operations = Diff(source.GetPropertiesInHierarchy(), target.GetPropertiesInHierarchy(), diffContext)
                             .Concat(Diff(source.GetKeys(), target.GetKeys(), diffContext))
                             .Concat(Diff(source.GetIndexesInHierarchy(), target.GetIndexesInHierarchy(), diffContext));

            foreach (var operation in operations)
            {
                yield return(operation);
            }
        }
Пример #4
0
 protected virtual IEnumerable <MigrationOperation> Diff(
     IEnumerable <IKey> source,
     IEnumerable <IKey> target,
     ModelDifferContext diffContext)
 => DiffCollection(
     source, target,
     Diff, Add, Remove,
     (s, t) => MetadataExtensions.Extensions(s).Name == MetadataExtensions.Extensions(t).Name &&
     s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties) &&
     s.IsPrimaryKey() == t.IsPrimaryKey());
Пример #5
0
 protected virtual IEnumerable <MigrationOperation> Diff(
     IEnumerable <IIndex> source,
     IEnumerable <IIndex> target,
     ModelDifferContext diffContext)
 => DiffCollection(
     source, target,
     Diff, Add, Remove,
     (s, t) => string.Equals(
         MetadataExtensions.Extensions(s).Name,
         MetadataExtensions.Extensions(t).Name,
         StringComparison.OrdinalIgnoreCase) &&
     s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties),
     (s, t) => s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties));
Пример #6
0
 protected virtual IEnumerable <MigrationOperation> Diff(
     IEnumerable <IForeignKey> source,
     IEnumerable <IForeignKey> target,
     ModelDifferContext diffContext)
 => DiffCollection(
     source,
     target,
     (s, t) => Diff(s, t, diffContext),
     t => Add(t, diffContext),
     s => Remove(s, diffContext),
     (s, t) =>
 {
     return(MetadataExtensions.Extensions(s).Name == MetadataExtensions.Extensions(t).Name &&
            s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties) &&
            diffContext.FindTarget(s.PrincipalEntityType.RootType()) == t.PrincipalEntityType.RootType() &&
            s.PrincipalKey.Properties.Select(diffContext.FindTarget).SequenceEqual(t.PrincipalKey.Properties));
 });
Пример #7
0
 protected virtual IEnumerable <MigrationOperation> Diff(
     [CanBeNull] IModel source,
     [CanBeNull] IModel target,
     [NotNull] ModelDifferContext diffContext)
 => source != null && target != null
         ? Diff(GetSchemas(source), GetSchemas(target))
 .Concat(Diff(source.GetRootEntityTypes(), target.GetRootEntityTypes(), diffContext))
 .Concat(
     Diff(MetadataExtensions.Extensions(source).Sequences, MetadataExtensions.Extensions(target).Sequences))
 .Concat(
     Diff(
         source.EntityTypes.SelectMany(t => t.GetForeignKeys()),
         target.EntityTypes.SelectMany(t => t.GetForeignKeys()),
         diffContext))
         : target != null
             ? Add(target, diffContext)
             : source != null
                 ? Remove(source, diffContext)
                 : Enumerable.Empty <MigrationOperation>();
Пример #8
0
        protected virtual IEnumerable <MigrationOperation> Diff(
            IEnumerable <IProperty> source,
            IEnumerable <IProperty> target,
            ModelDifferContext diffContext)
        => DiffCollection(
            source,
            target,
            (s, t) =>
        {
            diffContext.AddMapping(s, t);

            return(Diff(s, t));
        },
            t => Add(t),
            Remove,
            (s, t) => string.Equals(s.Name, t.Name, StringComparison.OrdinalIgnoreCase),
            (s, t) => string.Equals(
                MetadataExtensions.Extensions(s).Column,
                MetadataExtensions.Extensions(t).Column,
                StringComparison.OrdinalIgnoreCase));
Пример #9
0
 protected virtual IEnumerable <MigrationOperation> Diff(
     IEnumerable <IEntityType> source,
     IEnumerable <IEntityType> target,
     ModelDifferContext diffContext)
 => DiffCollection(
     source,
     target,
     (s, t) => Diff(s, t, diffContext),
     t => Add(t, diffContext),
     s => Remove(s, diffContext),
     (s, t) => string.Equals(s.Name, t.Name, StringComparison.OrdinalIgnoreCase),
     (s, t) => string.Equals(
         MetadataExtensions.Extensions(s).Schema,
         MetadataExtensions.Extensions(t).Schema,
         StringComparison.OrdinalIgnoreCase) &&
     string.Equals(
         MetadataExtensions.Extensions(s).Table,
         MetadataExtensions.Extensions(t).Table,
         StringComparison.OrdinalIgnoreCase),
     (s, t) => string.Equals(
         MetadataExtensions.Extensions(s).Table,
         MetadataExtensions.Extensions(t).Table,
         StringComparison.OrdinalIgnoreCase));
Пример #10
0
        protected virtual IReadOnlyList <MigrationOperation> Sort(
            [NotNull] IEnumerable <MigrationOperation> operations,
            [NotNull] ModelDifferContext diffContext)
        {
            Check.NotNull(operations, nameof(operations));

            var dropForeignKeyOperations = new List <MigrationOperation>();
            var dropOperations           = new List <MigrationOperation>();
            var dropColumnOperations     = new List <MigrationOperation>();
            var dropTableOperations      = new List <DropTableOperation>();
            var createSchemaOperations   = new List <MigrationOperation>();
            var createSequenceOperations = new List <MigrationOperation>();
            var createTableOperations    = new List <CreateTableOperation>();
            var alterOperations          = new List <MigrationOperation>();
            var renameOperations         = new List <MigrationOperation>();
            var renameIndexOperations    = new List <MigrationOperation>();
            var renameTableOperations    = new List <MigrationOperation>();
            var leftovers = new List <MigrationOperation>();

            foreach (var operation in operations)
            {
                var type = operation.GetType();
                if (type == typeof(DropForeignKeyOperation))
                {
                    dropForeignKeyOperations.Add(operation);
                }
                else if (_dropOperationTypes.Contains(type))
                {
                    dropOperations.Add(operation);
                }
                else if (type == typeof(DropColumnOperation))
                {
                    dropColumnOperations.Add(operation);
                }
                else if (type == typeof(DropTableOperation))
                {
                    dropTableOperations.Add((DropTableOperation)operation);
                }
                else if (type == typeof(CreateSchemaOperation))
                {
                    createSchemaOperations.Add(operation);
                }
                else if (type == typeof(CreateSequenceOperation))
                {
                    createSequenceOperations.Add(operation);
                }
                else if (type == typeof(CreateTableOperation))
                {
                    createTableOperations.Add((CreateTableOperation)operation);
                }
                else if (_alterOperationTypes.Contains(type))
                {
                    alterOperations.Add(operation);
                }
                else if (_renameOperationTypes.Contains(type))
                {
                    renameOperations.Add(operation);
                }
                else if (type == typeof(RenameIndexOperation))
                {
                    renameIndexOperations.Add(operation);
                }
                else if (type == typeof(RenameTableOperation))
                {
                    renameTableOperations.Add(operation);
                }
                else
                {
                    Debug.Assert(false, "Unexpected operation type: " + operation.GetType());
                    leftovers.Add(operation);
                }
            }

            var createTableGraph = new Multigraph <CreateTableOperation, AddForeignKeyOperation>();

            createTableGraph.AddVertices(createTableOperations);
            foreach (var createTableOperation in createTableOperations)
            {
                foreach (var addForeignKeyOperation in createTableOperation.ForeignKeys)
                {
                    if (addForeignKeyOperation.Table == addForeignKeyOperation.ReferencedTable &&
                        addForeignKeyOperation.Schema == addForeignKeyOperation.ReferencedSchema)
                    {
                        continue;
                    }

                    var principalCreateTableOperation = createTableOperations.FirstOrDefault(
                        o => o.Name == addForeignKeyOperation.ReferencedTable &&
                        o.Schema == addForeignKeyOperation.ReferencedSchema);
                    if (principalCreateTableOperation != null)
                    {
                        createTableGraph.AddEdge(principalCreateTableOperation, createTableOperation, addForeignKeyOperation);
                    }
                }
            }
            createTableOperations = createTableGraph.TopologicalSort(
                (principalCreateTableOperation, createTableOperation, addForeignKeyOperations) =>
            {
                foreach (var addForeignKeyOperation in addForeignKeyOperations)
                {
                    createTableOperation.ForeignKeys.Remove(addForeignKeyOperation);
                    alterOperations.Add(addForeignKeyOperation);
                }

                return(true);
            }).ToList();

            var dropTableGraph = new Multigraph <DropTableOperation, IForeignKey>();

            dropTableGraph.AddVertices(dropTableOperations);
            foreach (var dropTableOperation in dropTableOperations)
            {
                var entityType = diffContext.GetMetadata(dropTableOperation);
                foreach (var foreignKey in entityType.GetForeignKeysInHierarchy())
                {
                    var principalRootEntityType = foreignKey.PrincipalEntityType.RootType();
                    if (entityType == principalRootEntityType)
                    {
                        continue;
                    }

                    var principalDropTableOperation = diffContext.FindDrop(principalRootEntityType);
                    if (principalDropTableOperation != null)
                    {
                        dropTableGraph.AddEdge(dropTableOperation, principalDropTableOperation, foreignKey);
                    }
                }
            }
            var newDiffContext = new ModelDifferContext();

            dropTableOperations = dropTableGraph.TopologicalSort(
                (dropTableOperation, principalDropTableOperation, foreignKeys) =>
            {
                dropForeignKeyOperations.AddRange(foreignKeys.SelectMany(c => Remove(c, newDiffContext)));

                return(true);
            }).ToList();

            return(dropForeignKeyOperations
                   .Concat(dropOperations)
                   .Concat(dropColumnOperations)
                   .Concat(dropTableOperations)
                   .Concat(createSchemaOperations)
                   .Concat(createSequenceOperations)
                   .Concat(createTableOperations)
                   .Concat(alterOperations)
                   .Concat(renameOperations)
                   .Concat(renameIndexOperations)
                   .Concat(renameTableOperations)
                   .Concat(leftovers)
                   .ToArray());
        }
Пример #11
0
        public virtual IReadOnlyList <MigrationOperation> GetDifferences(IModel source, IModel target)
        {
            var diffContext = new ModelDifferContext();

            return(Sort(Diff(source, target, diffContext), diffContext));
        }
Пример #12
0
        protected virtual IEnumerable <MigrationOperation> Remove(IForeignKey source, ModelDifferContext diffContext)
        {
            var sourceExtensions           = MetadataExtensions.Extensions(source);
            var declaringRootEntityType    = source.DeclaringEntityType.RootType();
            var sourceEntityTypeExtensions = MetadataExtensions.Extensions(declaringRootEntityType);

            var dropTableOperation = diffContext.FindDrop(declaringRootEntityType);

            if (dropTableOperation == null)
            {
                yield return(new DropForeignKeyOperation
                {
                    Schema = sourceEntityTypeExtensions.Schema,
                    Table = sourceEntityTypeExtensions.Table,
                    Name = sourceExtensions.Name
                });
            }
        }
Пример #13
0
 protected virtual IEnumerable <MigrationOperation> Diff(IForeignKey source, IForeignKey target, ModelDifferContext diffContext)
 => HasDifferences(Annotations.For(source), Annotations.For(target))
         ? Remove(source, diffContext).Concat(Add(target, diffContext))
         : Enumerable.Empty <MigrationOperation>();
Пример #14
0
        protected virtual IEnumerable <MigrationOperation> Remove(IEntityType source, ModelDifferContext diffContext)
        {
            var sourceExtensions = MetadataExtensions.Extensions(source);

            var operation = new DropTableOperation
            {
                Schema = sourceExtensions.Schema,
                Name   = sourceExtensions.Table
            };

            diffContext.AddDrop(source, operation);

            yield return(operation);
        }
Пример #15
0
 protected virtual IEnumerable <MigrationOperation> Remove(IModel source, ModelDifferContext diffContext) =>
 source.GetRootEntityTypes().SelectMany(t => Remove(t, diffContext))
 .Concat(MetadataExtensions.Extensions(source).Sequences.SelectMany(Remove));
Пример #16
0
 protected virtual IEnumerable <MigrationOperation> Add(IModel target, ModelDifferContext diffContext)
 => GetSchemas(target).SelectMany(Add)
 .Concat(target.GetRootEntityTypes().SelectMany(t => Add(t, diffContext)))
 .Concat(MetadataExtensions.Extensions(target).Sequences.SelectMany(Add))
 .Concat(target.EntityTypes.SelectMany(t => t.GetForeignKeys()).SelectMany(k => Add(k, diffContext)));