FluentMigrator откатывается к столбцу Not Nullable?

Учитывая следующую миграцию:

[Migration(1)]
public class Mig001 : Migration
{
    public override void Up()
    {
        Alter.Table("foo").AlterColumn("bar").AsInt32().Nullable();
    }

    public override void Down()
    {
        Alter.Table("foo").AlterColumn("bar").AsInt32().NotNullable();
    }
}

Мигратор изменяет столбец и делает его нулевым, а при откате он выполняет обратное и снова делает его недействительным.

Допустим, что данные были добавлены в foo с момента перехода; теперь есть строки с нулевым значением в столбце bar.

Если он откатывается, операция будет терпеть неудачу, есть ли способ в fluentmigrator для обработки этого сценария? Или что лучше всего.

Ответ 1

Короткий ответ - установить значение по умолчанию для всех столбцов с нулевым значением. Вы можете сделать это только с помощью sql, используя выражение Execute.Sql. Это должно быть перед выражением Alter.Table.

public override void Down()
{
    Execute.Sql("update foo set bar = 0 where bar is null");
    Alter.Table("foo").AlterColumn("bar").AsInt32().NotNullable();
}

Долгий ответ заключается в том, что много работы всегда гарантирует, что вы сможете откатить миграцию и уверены, что вам нужно это сделать?

Например, если действие вверх - это создать таблицу, а действие вниз - удалить его, вы должны сохранить данные в таблице темп, чтобы она не исчезла? В большинстве случаев применение вниз используется при развертывании в тестовых средах или при откате неудачного развертывания, и довольно редко вы откатываете миграцию после ее развертывания.

Ответ 2

Вот альтернативный способ выполнения миграции, который не требует прямого выполнения SQL.

public override void Down()
{
    Update.Table("foo").Set(new { bar = 0 }).Where(new { bar = (int?) null });
    Alter.Table("foo").AlterColumn("bar").AsInt32().NotNullable();
}

Ответ 3

Старый раздел, но вы можете сделать это, чтобы присвоить существующим строкам новое значение:

            migration.Alter.Table("foo")
                .AlterColumn("bar")
                .AsDateTime()
                .NotNullable()
                .SetExistingRowsTo(DateTime.UtcNow)
            ;