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); } }
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); } }
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); } }
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());
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));
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)); });
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>();
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));
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));
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()); }
public virtual IReadOnlyList <MigrationOperation> GetDifferences(IModel source, IModel target) { var diffContext = new ModelDifferContext(); return(Sort(Diff(source, target, diffContext), diffContext)); }
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 }); } }
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>();
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); }
protected virtual IEnumerable <MigrationOperation> Remove(IModel source, ModelDifferContext diffContext) => source.GetRootEntityTypes().SelectMany(t => Remove(t, diffContext)) .Concat(MetadataExtensions.Extensions(source).Sequences.SelectMany(Remove));
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)));