protected virtual IEnumerable <MigrationOperation> Add([NotNull] IProperty target, bool inline = false)
        {
            var targetAnnotations           = Annotations.For(target);
            var targetEntityTypeAnnotations = Annotations.For(target.DeclaringEntityType.RootType());

            var operation = new AddColumnOperation
            {
                Schema       = targetEntityTypeAnnotations.Schema,
                Table        = targetEntityTypeAnnotations.TableName,
                Name         = targetAnnotations.ColumnName,
                ClrType      = target.ClrType.UnwrapNullableType().UnwrapEnumType(),
                ColumnType   = targetAnnotations.ColumnType,
                IsNullable   = target.IsColumnNullable(),
                DefaultValue = targetAnnotations.DefaultValue
                               ?? (inline || target.IsColumnNullable()
                                   ? null
                                   : GetDefaultValue(target.ClrType)),
                DefaultValueSql   = target.ValueGenerated == ValueGenerated.OnAdd ? targetAnnotations.GeneratedValueSql : null,
                ComputedColumnSql = target.ValueGenerated == ValueGenerated.OnAddOrUpdate ? targetAnnotations.GeneratedValueSql : null
            };

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

            yield return(operation);
        }
        protected virtual void CreateIndexes(
            [CanBeNull] IProperty property,
            [NotNull] MigrationCommandListBuilder builder)
        {
            Check.NotNull(builder, nameof(builder));

            if (property == null)
            {
                return;
            }

            foreach (var index in property.GetContainingIndexes())
            {
                var operation = new CreateIndexOperation
                {
                    IsUnique = index.IsUnique,
                    Name     = Annotations.For(index).Name,
                    Schema   = Annotations.For(index.DeclaringEntityType).Schema,
                    Table    = Annotations.For(index.DeclaringEntityType).TableName,
                    Columns  = index.Properties.Select(p => Annotations.For(p).ColumnName).ToArray()
                };
                operation.AddAnnotations(_migrationsAnnotations.For(index));

                Generate(operation, index.DeclaringEntityType.Model, builder, terminate: false);
                builder.AppendLine(SqlGenerationHelper.StatementTerminator);
            }
        }
        protected virtual IEnumerable <MigrationOperation> Add(IForeignKey target, DiffContext diffContext)
        {
            var declaringRootEntityType              = target.DeclaringEntityType.RootType();
            var targetEntityTypeAnnotations          = Annotations.For(declaringRootEntityType);
            var targetPrincipalEntityTypeAnnotations = Annotations.For(target.PrincipalEntityType.RootType());

            // TODO: Set OnDelete (See #1084)
            var operation = new AddForeignKeyOperation
            {
                Schema           = targetEntityTypeAnnotations.Schema,
                Table            = targetEntityTypeAnnotations.TableName,
                Name             = Annotations.For(target).Name,
                Columns          = GetColumns(target.Properties),
                PrincipalSchema  = targetPrincipalEntityTypeAnnotations.Schema,
                PrincipalTable   = targetPrincipalEntityTypeAnnotations.TableName,
                PrincipalColumns = GetColumns(target.PrincipalKey.Properties)
            };

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

            var createTableOperation = diffContext.FindCreate(declaringRootEntityType);

            if (createTableOperation != null)
            {
                createTableOperation.ForeignKeys.Add(operation);
            }
            else
            {
                yield return(operation);
            }
        }
        protected virtual IEnumerable <MigrationOperation> Add([NotNull] IForeignKey target, [NotNull] DiffContext diffContext)
        {
            var declaringRootEntityType              = target.DeclaringEntityType.RootType();
            var targetEntityTypeAnnotations          = Annotations.For(declaringRootEntityType);
            var targetPrincipalEntityTypeAnnotations = Annotations.For(target.PrincipalEntityType.RootType());

            var operation = new AddForeignKeyOperation
            {
                Schema           = targetEntityTypeAnnotations.Schema,
                Table            = targetEntityTypeAnnotations.TableName,
                Name             = Annotations.For(target).Name,
                Columns          = GetColumns(target.Properties),
                PrincipalSchema  = targetPrincipalEntityTypeAnnotations.Schema,
                PrincipalTable   = targetPrincipalEntityTypeAnnotations.TableName,
                PrincipalColumns = GetColumns(target.PrincipalKey.Properties),
                OnDelete         = target.DeleteBehavior == DeleteBehavior.Cascade
                    ? ReferentialAction.Cascade
                    : target.DeleteBehavior == DeleteBehavior.SetNull
                        ? ReferentialAction.SetNull
                        : ReferentialAction.Restrict
            };

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

            var createTableOperation = diffContext.FindCreate(declaringRootEntityType);

            if (createTableOperation != null)
            {
                createTableOperation.ForeignKeys.Add(operation);
            }
            else
            {
                yield return(operation);
            }
        }
        protected virtual IEnumerable <MigrationOperation> Add([NotNull] IKey target)
        {
            var targetAnnotations           = Annotations.For(target);
            var targetEntityTypeAnnotations = Annotations.For(target.DeclaringEntityType.RootType());

            MigrationOperation operation;

            if (target.IsPrimaryKey())
            {
                operation = new AddPrimaryKeyOperation
                {
                    Schema  = targetEntityTypeAnnotations.Schema,
                    Table   = targetEntityTypeAnnotations.TableName,
                    Name    = targetAnnotations.Name,
                    Columns = GetColumns(target.Properties)
                };
            }
            else
            {
                operation = new AddUniqueConstraintOperation
                {
                    Schema  = targetEntityTypeAnnotations.Schema,
                    Table   = targetEntityTypeAnnotations.TableName,
                    Name    = targetAnnotations.Name,
                    Columns = GetColumns(target.Properties)
                };
            }
            CopyAnnotations(MigrationsAnnotations.For(target), operation);

            yield return(operation);
        }
        protected virtual IEnumerable <MigrationOperation> Diff(
            [NotNull] IEntityType source,
            [NotNull] IEntityType target,
            [NotNull] DiffContext diffContext)
        {
            var sourceAnnotations = Annotations.For(source);
            var targetAnnotations = Annotations.For(target);

            var schemaChanged = sourceAnnotations.Schema != targetAnnotations.Schema;
            var renamed       = sourceAnnotations.TableName != targetAnnotations.TableName;

            if (schemaChanged || renamed)
            {
                yield return(new RenameTableOperation
                {
                    Schema = sourceAnnotations.Schema,
                    Name = sourceAnnotations.TableName,
                    NewSchema = schemaChanged ? targetAnnotations.Schema : null,
                    NewName = renamed ? targetAnnotations.TableName : null
                });
            }

            diffContext.AddMapping(source, target);

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

            foreach (var operation in operations)
            {
                yield return(operation);
            }
        }
        protected virtual IEnumerable <MigrationOperation> Add([NotNull] IEntityType target, [NotNull] DiffContext diffContext)
        {
            var targetAnnotations = Annotations.For(target);

            var createTableOperation = new CreateTableOperation
            {
                Schema = targetAnnotations.Schema,
                Name   = targetAnnotations.TableName
            };

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

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

            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 GetIndexesInHierarchy(target).SelectMany(Add))
            {
                yield return(operation);
            }
        }
        protected virtual IEnumerable <MigrationOperation> Diff([NotNull] IIndex source, [NotNull] IIndex target)
        {
            var sourceEntityTypeAnnotations = Annotations.For(source.DeclaringEntityType.RootType());
            var sourceName = Annotations.For(source).Name;
            var targetName = Annotations.For(target).Name;

            if (sourceName != targetName)
            {
                yield return(new RenameIndexOperation
                {
                    Schema = sourceEntityTypeAnnotations.Schema,
                    Table = sourceEntityTypeAnnotations.TableName,
                    Name = sourceName,
                    NewName = targetName
                });
            }

            if ((source.IsUnique != target.IsUnique) ||
                HasDifferences(MigrationsAnnotations.For(source), MigrationsAnnotations.For(target)))
            {
                var operations = Remove(source).Concat(Add(target));
                foreach (var operation in operations)
                {
                    yield return(operation);
                }
            }
        }
        protected virtual void DropIndexes(
            [CanBeNull] IProperty property,
            [NotNull] MigrationCommandListBuilder builder)
        {
            Check.NotNull(builder, nameof(builder));

            if (property == null)
            {
                return;
            }

            foreach (var index in property.GetContainingIndexes())
            {
                var operation = new DropIndexOperation
                {
                    Schema = Annotations.For(index.DeclaringEntityType).Schema,
                    Table  = Annotations.For(index.DeclaringEntityType).TableName,
                    Name   = Annotations.For(index).Name
                };
                operation.AddAnnotations(_migrationsAnnotations.ForRemove(index));

                Generate(operation, index.DeclaringEntityType.Model, builder, terminate: false);
                builder.AppendLine(SqlGenerationHelper.StatementTerminator);
            }
        }
Esempio n. 10
0
        protected virtual IEnumerable <MigrationOperation> Diff([NotNull] IProperty source, [NotNull] IProperty target)
        {
            var sourceAnnotations           = Annotations.For(source);
            var sourceEntityTypeAnnotations = Annotations.For(source.DeclaringEntityType.RootType());
            var targetAnnotations           = Annotations.For(target);

            if (sourceAnnotations.ColumnName != targetAnnotations.ColumnName)
            {
                yield return(new RenameColumnOperation
                {
                    Schema = sourceEntityTypeAnnotations.Schema,
                    Table = sourceEntityTypeAnnotations.TableName,
                    Name = sourceAnnotations.ColumnName,
                    NewName = targetAnnotations.ColumnName
                });
            }

            var sourceColumnType = sourceAnnotations.ColumnType
                                   ?? TypeMapper.GetMapping(source).DefaultTypeName;
            var targetColumnType = targetAnnotations.ColumnType
                                   ?? TypeMapper.GetMapping(target).DefaultTypeName;

            var targetMigrationsAnnotations = MigrationsAnnotations.For(target);

            var isSourceColumnNullable = source.IsColumnNullable();
            var isTargetColumnNullable = target.IsColumnNullable();
            var isNullableChanged      = isSourceColumnNullable != isTargetColumnNullable;
            var columnTypeChanged      = sourceColumnType != targetColumnType;

            if (isNullableChanged ||
                columnTypeChanged ||
                sourceAnnotations.DefaultValueSql != targetAnnotations.DefaultValueSql ||
                sourceAnnotations.ComputedValueSql != targetAnnotations.ComputedValueSql ||
                !Equals(sourceAnnotations.DefaultValue, targetAnnotations.DefaultValue) ||
                HasDifferences(MigrationsAnnotations.For(source), targetMigrationsAnnotations))
            {
                var isDestructiveChange = (isNullableChanged && isSourceColumnNullable)
                                          // TODO: Detect type narrowing
                                          || columnTypeChanged;

                var alterColumnOperation = new AlterColumnOperation
                {
                    Schema              = sourceEntityTypeAnnotations.Schema,
                    Table               = sourceEntityTypeAnnotations.TableName,
                    Name                = sourceAnnotations.ColumnName,
                    ClrType             = target.ClrType.UnwrapNullableType().UnwrapEnumType(),
                    ColumnType          = targetAnnotations.ColumnType,
                    IsNullable          = isTargetColumnNullable,
                    DefaultValue        = targetAnnotations.DefaultValue,
                    DefaultValueSql     = targetAnnotations.DefaultValueSql,
                    ComputedColumnSql   = targetAnnotations.ComputedValueSql,
                    IsDestructiveChange = isDestructiveChange
                };
                CopyAnnotations(targetMigrationsAnnotations, alterColumnOperation);

                yield return(alterColumnOperation);
            }
        }
 protected virtual IEnumerable <MigrationOperation> Diff(
     [NotNull] IEnumerable <IKey> source,
     [NotNull] IEnumerable <IKey> target,
     [NotNull] DiffContext diffContext)
 => DiffCollection(
     source, target,
     Diff, Add, Remove,
     (s, t) => (Annotations.For(s).Name == Annotations.For(t).Name) &&
     s.Properties.Select(diffContext.FindTarget).SequenceEqual(t.Properties) &&
     (s.IsPrimaryKey() == t.IsPrimaryKey()));
        protected virtual IEnumerable <MigrationOperation> Remove([NotNull] IIndex source)
        {
            var sourceEntityTypeAnnotations = Annotations.For(source.DeclaringEntityType.RootType());

            yield return(new DropIndexOperation
            {
                Name = Annotations.For(source).Name,
                Schema = sourceEntityTypeAnnotations.Schema,
                Table = sourceEntityTypeAnnotations.TableName
            });
        }
        protected virtual IEnumerable <MigrationOperation> Remove(IProperty source)
        {
            var sourceEntityTypeAnnotations = Annotations.For(source.DeclaringEntityType.RootType());

            yield return(new DropColumnOperation
            {
                Schema = sourceEntityTypeAnnotations.Schema,
                Table = sourceEntityTypeAnnotations.TableName,
                Name = Annotations.For(source).ColumnName
            });
        }
 protected virtual IEnumerable <MigrationOperation> Diff(
     [NotNull] IEnumerable <IIndex> source,
     [NotNull] IEnumerable <IIndex> target,
     [NotNull] DiffContext diffContext)
 => DiffCollection(
     source, target,
     Diff, Add, Remove,
     (s, t) => string.Equals(
         Annotations.For(s).Name,
         Annotations.For(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> Remove(IEntityType source, DiffContext diffContext)
        {
            var sourceAnnotations = Annotations.For(source);

            var operation = new DropTableOperation
            {
                Schema = sourceAnnotations.Schema,
                Name   = sourceAnnotations.TableName
            };

            diffContext.AddDrop(source, operation);

            yield return(operation);
        }
 protected virtual IEnumerable <MigrationOperation> Diff(
     [NotNull] IEnumerable <IForeignKey> source,
     [NotNull] IEnumerable <IForeignKey> target,
     [NotNull] DiffContext diffContext)
 => DiffCollection(
     source,
     target,
     (s, t) => Diff(s, t, diffContext),
     t => Add(t, diffContext),
     s => Remove(s, diffContext),
     (s, t) => (Annotations.For(s).Name == Annotations.For(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) &&
     (s.DeleteBehavior == t.DeleteBehavior));
 protected virtual IEnumerable <MigrationOperation> Diff(
     IEnumerable <IForeignKey> source,
     IEnumerable <IForeignKey> target,
     DiffContext diffContext)
 => DiffCollection(
     source,
     target,
     (s, t) => Diff(s, t, diffContext),
     t => Add(t, diffContext),
     s => Remove(s, diffContext),
     (s, t) =>
 {
     return(Annotations.For(s).Name == Annotations.For(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> Add([NotNull] IIndex target)
        {
            var targetEntityTypeAnnotations = Annotations.For(target.DeclaringEntityType.RootType());

            var operation = new CreateIndexOperation
            {
                Name     = Annotations.For(target).Name,
                Schema   = targetEntityTypeAnnotations.Schema,
                Table    = targetEntityTypeAnnotations.TableName,
                Columns  = GetColumns(target.Properties),
                IsUnique = target.IsUnique
            };

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

            yield return(operation);
        }
        protected virtual IEnumerable <MigrationOperation> Remove([NotNull] IForeignKey source, [NotNull] DiffContext diffContext)
        {
            var declaringRootEntityType     = source.DeclaringEntityType.RootType();
            var sourceEntityTypeAnnotations = Annotations.For(declaringRootEntityType);

            var dropTableOperation = diffContext.FindDrop(declaringRootEntityType);

            if (dropTableOperation == null)
            {
                yield return(new DropForeignKeyOperation
                {
                    Schema = sourceEntityTypeAnnotations.Schema,
                    Table = sourceEntityTypeAnnotations.TableName,
                    Name = Annotations.For(source).Name
                });
            }
        }
 protected virtual IEnumerable <MigrationOperation> Diff(
     [CanBeNull] IModel source,
     [CanBeNull] IModel target,
     [NotNull] DiffContext diffContext)
 => (source != null) && (target != null)
         ? Diff(GetSchemas(source), GetSchemas(target))
 .Concat(Diff(source.GetRootEntityTypes(), target.GetRootEntityTypes(), diffContext))
 .Concat(
     Diff(Annotations.For(source).Sequences, Annotations.For(target).Sequences))
 .Concat(
     Diff(
         source.GetEntityTypes().SelectMany(t => t.GetDeclaredForeignKeys()),
         target.GetEntityTypes().SelectMany(t => t.GetDeclaredForeignKeys()),
         diffContext))
         : target != null
             ? Add(target, diffContext)
             : source != null
                 ? Remove(source, diffContext)
                 : Enumerable.Empty <MigrationOperation>();
        protected virtual IEnumerable <MigrationOperation> Diff(
            [NotNull] IEnumerable <IProperty> source,
            [NotNull] IEnumerable <IProperty> target,
            [NotNull] DiffContext 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(
                Annotations.For(s).ColumnName,
                Annotations.For(t).ColumnName,
                StringComparison.OrdinalIgnoreCase));
 protected virtual IEnumerable <MigrationOperation> Diff(
     [NotNull] IEnumerable <IEntityType> source,
     [NotNull] IEnumerable <IEntityType> target,
     [NotNull] DiffContext 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(
         Annotations.For(s).Schema,
         Annotations.For(t).Schema,
         StringComparison.OrdinalIgnoreCase) &&
     string.Equals(
         Annotations.For(s).TableName,
         Annotations.For(t).TableName,
         StringComparison.OrdinalIgnoreCase),
     (s, t) => string.Equals(
         Annotations.For(s).TableName,
         Annotations.For(t).TableName,
         StringComparison.OrdinalIgnoreCase));
        protected virtual IEnumerable <MigrationOperation> Remove([NotNull] IKey source)
        {
            var sourceAnnotations           = Annotations.For(source);
            var sourceEntityTypeAnnotations = Annotations.For(source.DeclaringEntityType.RootType());

            if (source.IsPrimaryKey())
            {
                yield return(new DropPrimaryKeyOperation
                {
                    Schema = sourceEntityTypeAnnotations.Schema,
                    Table = sourceEntityTypeAnnotations.TableName,
                    Name = sourceAnnotations.Name
                });
            }
            else
            {
                yield return(new DropUniqueConstraintOperation
                {
                    Schema = sourceEntityTypeAnnotations.Schema,
                    Table = sourceEntityTypeAnnotations.TableName,
                    Name = sourceAnnotations.Name
                });
            }
        }
 protected virtual IEnumerable <string> GetSchemas([NotNull] IModel model)
 => model.GetRootEntityTypes().Select(t => Annotations.For(t).Schema).Where(s => !string.IsNullOrEmpty(s))
 .Distinct();
 protected virtual string[] GetColumns([NotNull] IEnumerable <IProperty> properties)
 => properties.Select(p => Annotations.For(p).ColumnName).ToArray();
 protected virtual IEnumerable <MigrationOperation> Add([NotNull] IModel target, [NotNull] DiffContext diffContext)
 => GetSchemas(target).SelectMany(Add)
 .Concat(target.GetRootEntityTypes().SelectMany(t => Add(t, diffContext)))
 .Concat(Annotations.For(target).Sequences.SelectMany(Add))
 .Concat(target.GetEntityTypes().SelectMany(t => t.GetDeclaredForeignKeys()).SelectMany(k => Add(k, diffContext)));
 protected virtual IEnumerable <MigrationOperation> Remove([NotNull] IModel source, [NotNull] DiffContext diffContext) =>
 source.GetRootEntityTypes().SelectMany(t => Remove(t, diffContext))
 .Concat(Annotations.For(source).Sequences.SelectMany(Remove));
 private IEnumerable <IIndex> GetIndexesInHierarchy(IEntityType entityType)
 => entityType.GetDeclaredIndexes().Concat(entityType.GetDerivedTypes().SelectMany(t => t.GetDeclaredIndexes()))
 .Distinct((x, y) => Annotations.For(x).Name == Annotations.For(y).Name);
 private IEnumerable <IProperty> GetPropertiesInHierarchy(IEntityType entityType)
 => entityType.GetDeclaredProperties().Concat(entityType.GetDerivedTypes().SelectMany(t => t.GetDeclaredProperties()))
 .Distinct((x, y) => Annotations.For(x).ColumnName == Annotations.For(y).ColumnName);