2013-06-10 9 views
10

Dati i seguenti migrazione:FluentMigrator ritorna su una colonna 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(); 
    } 
} 

Il migratore altera una colonna e rende annullabile e sul ripristino avviene il contrario e rende non annullabile nuovamente.

Diciamo che i dati sono stati aggiunti a foo dalla migrazione; ora ci sono righe con null nella colonna bar.

Se viene eseguito il rollback, l'operazione avrà esito negativo, è possibile che in fluentmigrator sia in grado di gestire questo scenario? O qual è la migliore pratica.

risposta

10

La risposta breve è impostare un valore predefinito per tutte le colonne che hanno un valore nullable. Puoi farlo solo con sql usando l'espressione Execute.Sql. Questo dovrebbe essere prima dell'espressione Alter.Table.

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

La risposta lunga è che si tratta di un sacco di lavoro al fine di garantire sempre che si può rollback di una migrazione e sei sicuro che devi fare che?

Ad esempio, se l'azione su è quella di creare una tabella e l'azione verso il basso è di rilasciarla, è necessario salvare i dati in una tabella temporanea in modo che non scompaia? Per la maggior parte dei casi d'uso, l'azione down viene utilizzata durante la distribuzione in ambienti di test o durante il rollback di una distribuzione non riuscita ed è abbastanza raro che si ripristini una migrazione dopo che è stata distribuita.

+0

Sto indovinando che non avrebbe funzionato se 'bar' era una colonna di chiave esterna? Un metodo Down può essere lasciato vuoto? – user1838662

+0

Se è una colonna di chiave esterna, la query sql dovrà essere un po 'più intelligente e trovare il valore corretto da impostare. O hai un valore di chiave esterna che funzionerebbe come predefinito? –

+0

Sfortunatamente non esiste un valore di chiave esterna predefinito. '0' Punterebbe a un record nella tabella padre che non esiste. – user1838662

6

Ecco un modo alternativo di eseguire la migrazione che non richiede l'esecuzione diretta di SQL.

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

argomento vecchio, ma si può fare questo per dare righe esistenti bis (nuovo) Valore:

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

ma SetExistingRowsTo aggiunge la condizione 'where bar is null'? Oppure usa tutte le righe ... – Serg046

+0

SetExistingRowsTo imposterà * tutte * le righe esistenti, poiché l'intento era quello di aggiungere colonne non nulle senza un semplice predefinito. Avremmo bisogno di un helper aggiuntivo come SetNullRowsTo o qualcosa del genere, ma per essere onesti, in un caso di aggiornamento di una colonna esistente da null a non null, penso che l'utilizzo del metodo suggerito da Lucas sia l'approccio migliore e non si tradurrà in intasare l'api con metodi spuri di aiuto. – Mike

Problemi correlati