예제 #1
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
                });
            }
        }
예제 #2
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());
        }