2012-06-03 2 views
24

Wenn Sie einer Tabelle mithilfe von Code-Erstmigrationen eine neue Spalte hinzufügen, die keine NULL-Werte zulässt, wird automatisch ein Standardwert für Sie erstellt. Dies ist sinnvoll, da vorhandene Zeilen einen Wert für die neue Spalte haben müssen (da sie nicht null sein kann). Das ist in Ordnung, aber nachdem dieser Wert überall zugewiesen wurde, will ich es nicht mehr. Es ist nicht nullbar, weil ich sicherstellen möchte, dass ein Wert immer explizit eingefügt wird. Wenn alles auf '' oder 0 steht, dann habe ich magische Saiten. Wie auch immer, ich kann mit einer Lösung aufwarten, von der ich nicht begeistert bin, aber es funktioniert.Entfernen einer Standardeinschränkung nach dem Hinzufügen einer neuen Spalte im Code zuerst

Nach dem Hinzufügen der Spalte, lasse ich dann die Standardbedingung fallen.

public override void Up() 
{ 
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false)); 
    Sql(Helpers.DropDefaultConstraint("dbo.SomeTable", "NewColumn")); 
} 

...

public static string DropDefaultConstraint(string table, string column) 
{ 
    return string.Format(@" 
     DECLARE @name sysname 

     SELECT @name = dc.name 
     FROM sys.columns c 
     JOIN sys.default_constraints dc ON dc.object_id = c.default_object_id 
     WHERE c.object_id = OBJECT_ID('{0}') 
     AND c.name = '{1}' 

     IF @name IS NOT NULL 
      EXECUTE ('ALTER TABLE {0} DROP CONSTRAINT ' + @name) 
     ", 
     table, column); 
} 

PROS: Sobald die Hilfsmethode implementiert ist, ich brauche nur eine einfache Linie hinzuzufügen, um die Einschränkung fallen zu lassen. CONS: Es scheint unnötig, einen Index zu erstellen, nur um ihn zu löschen.

Ein anderer Ansatz wäre, die generierte Migration zu ändern, also fügen wir hinzu, dass es nullable ist, alle Werte aktualisiert und dann nicht nullfähig gemacht wird.

public override void Up() 
{ 
    AddColumn("dbo.SomeTable", "NewColumn", c => c.Int()); 
    Sql("UPDATE dbo.SomeTableSET NewColumn= 1"); 
    AlterColumn("dbo.SomeTable", "NewColumn", c => c.Int(nullable: false)); 
} 

PROS: Scheint einfacher/Reiniger

CONTRA: Habe meine Zwänge vorübergehend zu ändern (ich nehme an, dies in einer Transaktion ausgeführt wird und somit sollten wir nicht schlechte Daten in ermöglicht werden). Das Update kann bei großen Tabellen langsam sein.

Welche Methode ist vorzuziehen? Oder gibt es einen besseren Weg, den ich vermisse?

Hinweis: Ich habe den Fall demonstriert, in dem Sie Spaltendefinitionen auf einmal hinzufügen und säubern. Wenn Sie nur die Standardwerte früherer Migrationen bereinigen, ist der zweite Ansatz nicht hilfreich.

+2

Lösung 1 half mir, eine Standardbedingung zu entfernen, danke. – angularsen

+0

das ist genial –

Antwort

10

Persönlich kann ich nichts falsch mit dem ersten Ansatz sehen. Ja, Sie müssen eine Standardbedingung erstellen, um eine nicht nullfähige Spalte zu einer nicht leeren Datenmenge hinzuzufügen. Und ja, Sie müssen es später löschen, wenn Sie sicherstellen müssen, dass die neue Spalte in Zukunft immer explizit hinzugefügt wird, gemäß Ihrer Anforderung.

Und selbst wenn Sie immer noch Probleme mit diesem Ansatz haben, ist das Problem, es gibt höchstwahrscheinlich keine andere Alternative außer Ihrem zweiten Ansatz. Und die Kosten für das Aktualisieren einer möglicherweise großen Tabelle mit einem Standardwert erscheinen mir größer als die Kosten für das Erstellen und sofortige Löschen einer Standardeinschränkung.

Ich könnte eine geringfügige Änderung betrachten, aber: Ich könnte die Einschränkung in SQL erstellen die fuss des Nachschlagens den Standardnamen durch den Motor, so etwas wie dies zugewiesen zu vermeiden:

Sql("ALTER TABLE tablename 
    ADD columnnametype NOT NULL 
    CONSTRAINT DF_tablename_columnname DEFAULT defaultvalue"); 

(Könnte neu geschrieben werden zu verwenden, würde eine einzelne ALTER TABLE-Anweisung als trivial sein, eine Hilfsfunktion)

einen Constraint Dropping dann als die Ausführung.

Sql("ALTER TABLE tablename 
    DROP CONSTRAINT DF_tablename_columnname"); 

(Wieder ein Hilfsfunktion könnte hier leicht verwendet werden.)

Aber das könnte ein T-SQL-Entwickler in mir sein, der lauter als ein C# one spricht.Sie können also sehr gut mit dem Code wie dem von Ihnen geposteten Beispiel arbeiten.

+0

Danke für die Validierung meiner Gedanken. Ich habe erwogen, die Einschränkung selbst zu erstellen, aber ich bevorzuge AddColumn, da es einfach und konsistent zu lesen ist und auch einige andere Einschränkungen zulässt, wie zum Beispiel unique. Ich entschied mich, bei Option 1 zu bleiben. Danke. –

Verwandte Themen