2013-06-10 6 views
10

die folgende Migration Gegeben:FluentMigrator Rollback zurück zu einer nicht Nullable Spalte?

[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(); 
    } 
} 

Der Migrator ändert eine Spalte und macht es auf NULL festlegbare und bei der Rücknahme tut es das Gegenteil und macht es wieder nicht nullable.

Nehmen wir an, Daten wurden seit der Migration zu foo hinzugefügt; Es gibt jetzt Zeilen mit Null in bar Spalte.

Wenn es zurückgerollt wird, dann wird der Vorgang fehlschlagen, gibt es irgendeinen Weg in fluentmigrator, dieses Szenario zu behandeln? Oder was ist die beste Vorgehensweise?

Antwort

10

Die kurze Antwort besteht darin, einen Standardwert für alle Spalten festzulegen, die einen Nullwert haben. Sie können dies nur mit SQL ausführen, indem Sie den Execute.Sql-Ausdruck verwenden. Dies sollte vor dem Alter.Table-Ausdruck sein.

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

Die lange Antwort ist, dass es eine Menge Arbeit ist immer um sicherzustellen, dass Sie eine Migration zurückzudrängen und sind Sie sicher, dass Sie das tun müssen?

Wenn beispielsweise die Aktion up eine Tabelle erstellen soll und die Aktion down, um sie zu löschen, sollten Sie die Daten in einer temporären Tabelle speichern, damit sie nicht verschwindet? In den meisten Anwendungsfällen wird die Aktion "Herunterfahren" beim Bereitstellen in Testumgebungen oder beim Zurücksetzen einer fehlgeschlagenen Bereitstellung verwendet. Es ist sehr selten, dass Sie eine Migration nach der Bereitstellung rückgängig machen.

+0

Ich vermute, das würde nicht funktionieren, wenn 'bar' eine Fremdschlüsselspalte ist? Kann eine Down-Methode leer gelassen werden? – user1838662

+0

Wenn es sich um eine Fremdschlüsselspalte handelt, muss die SQL-Abfrage etwas intelligenter sein und den richtigen Wert finden. Oder haben Sie einen Fremdschlüsselwert, der standardmäßig funktioniert? –

+0

Leider gibt es keinen Standard-Fremdschlüsselwert. '0' würde auf einen Datensatz in der übergeordneten Tabelle zeigen, der nicht existiert. – user1838662

6

Hier ist eine alternative Möglichkeit zur Durchführung der Migration, die keine direkte SQL-Ausführung erfordert.

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

altes Thema, aber Sie können dies einen (neuen) Wert vorhandene Zeilen geben tun:

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

, aber setzt SetExistingRowsTo die Bedingung 'where bar is null '? Oder es verwendet alle Zeilen ... – Serg046

+0

SetExistingRowsTo wird * alle * vorhandenen Zeilen setzen, da es das Hinzufügen von Nicht-Null-Spalten ohne Standard als einfach machen soll. Wir brauchen einen zusätzlichen Helfer wie SetNullRowsTo oder etwas ähnliches, aber um ehrlich zu sein, wenn ich eine existierende Spalte von null auf nicht null aktualisiere, denke ich, dass die Verwendung der von Lucas vorgeschlagenen Methode der beste Ansatz ist und nicht dazu führt Verstopfung der API mit falschen Hilfsmethoden. – Mike

Verwandte Themen