Wie benenne ich eine Datenbankspalte in Entity Framework 5 Code First-Migrationen um, ohne Daten zu verlieren?

72

Ich habe die Standardvorlage für ASP.NET MVC 4 erfolgreich mit EF 5.0 Code First Migrations ausgeführt. Wenn ich jedoch einen Modelleigenschaftsnamen aktualisiere, werden die entsprechenden Tabellenspaltendaten von EF 5.0 gelöscht.

Ist es irgendwie möglich, die Tabellenspalte umzubenennen, ohne Daten automatisch zu löschen?

Dante
quelle

Antworten:

112

Manuell bearbeiten die Up- und Down - Methoden der Migration die verwenden RenameColumnMethode , um das zu ersetzen AddColumnund DropColumndass es generiert automatisch für Sie.

Josh Gallagher
quelle
10
Seien Sie vorsichtig mit Tabellennamen, die Punkte enthalten. RenameColumngeneriert eine sp_renameT-SQL-Anweisung, die parsenameinterne Verwendungen verwendet, die einige Einschränkungen aufweisen. Wenn Sie also einen Tabellennamen haben, der Punkte enthält, z. B. "SubSystemA.Tabellenname", verwenden Sie:RenameColumn("dbo.[SubSystemA.Tablename]", "OldColumnName", "NewColumnName");
Ilan
Ich denke, diese Antwort setzt voraus, dass Sie AutomaticMigration = truedann Befehl ausführen Add-Migration renameColumnXXX. DropColumnAddColum
Überprüfen Sie anschließend
45

Wie bereits gesagt , ersetzen Sie das AddColumnund DropColumndas wird automatisch durch generiert RenameColumn.

Beispiel:

namespace MyProject.Model.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class RenameMyColumn : DbMigration
    {
        public override void Up()
        {
            // Remove the following auto-generated lines
            AddColumn("dbo.MyTable", "NewColumn", c => c.String(nullable: false, maxLength: 50));
            DropColumn("dbo.MyTable", "OldColumn");

            // Add this line
            RenameColumn("dbo.MyTable", "OldColumn", "NewColumn");
        }

        public override void Down()
        {
            // Remove the following auto-generated lines
            AddColumn("dbo.MyTable", "OldColumn", c => c.String(nullable: false, maxLength: 50));
            DropColumn("dbo.MyTable", "NewColumn");

            // Add this line
            RenameColumn("dbo.MyTable", "NewColumn", "OldColumn");
        }
    }
}
Zanon
quelle
19

Sie können die Migration RenameColumnfür Sie aufrufen lassen, wenn Sie dies tun:

[Column("NewName")]
public string OldName { get; set; }

Hier ist die generierte Migration:

    public override void Up()
    {
        RenameColumn(table: "Schema.MyTable", name: "OldName", newName: "NewName");
    }

    public override void Down()
    {
        RenameColumn(table: "Schema.MyTable", name: "NewName", newName: "OldName");
    }

Wenn Ihre Eigenschaft und Ihre DB-Spalte denselben Namen haben sollen, können Sie die Eigenschaft später umbenennen und das ColumnAttribut entfernen .

Jess
quelle
1
Und um einen weiteren nützlichen Tipp einzugeben, können Sie diesen auch in der Package Manager-Konsole ausführen : Update-Database -Script. Dann können Sie den SQL- sp_renameBefehl nach Belieben ausführen lassen. : D
Jess
1
Bevorzugter Ansatz, da auch der Eigenschaftsname des Modells angesprochen wird. Und ich habe überprüft, ob im optionalen zweiten Schritt des Umbenennens der Eigenschaft eine leere Migration generiert wird.
bvj
4

Diese Antwort basiert auf meinen Kenntnissen in EF4.3, daher hoffe ich, dass die Migrationen in EF5 ungefähr gleich funktionieren :) Nachdem Sie eine Migration erstellt haben, sollten Sie in der Lage sein, Code in den Up- und Down-Methoden zwischen hinzuzufügen das Löschen des alten Eigentums und die Schaffung des neuen Eigentums. Dieser Code sollte die Eigenschaftsdaten in die richtige Richtung verschieben. Ich habe es mit der SQL () -Methode gelöst, bei der Sie Roh-SQL eingeben können, um die Datenverschiebung durchzuführen.

In der Up-Methode der Migration:

SQL("update [TheTable] set [NewColumn] = [OldColumn]");

und in der Down () -Methode:

SQL("update [TheTable] set [OldColumn] = [NewColumn]");

Der Nachteil dieses Ansatzes besteht darin, dass Sie Ihren Code möglicherweise mit der Datenbank koppeln, mit der Sie gerade arbeiten (da Sie rohes DB-spezifisches SQL schreiben). Möglicherweise stehen auch andere Methoden für die Datenverschiebung zur Verfügung.

Weitere Informationen finden Sie hier: MSDN

Daniel Persson
quelle
4

Sie haben zwei Schritte, um die Spalte in der ersten Code-Migration umzubenennen

  1. Im ersten Schritt fügen Sie ColumnAttribute über Ihrer geänderten Spalte hinzu und aktualisieren dann die Datenbank

[Spalte ("Inhalt")]
öffentliche Zeichenfolge Beschreibung {set; erhalten; }}

  1. Der zweite Schritt,

    • Befehl add-migration yournamechange, um eine Teilklasse DbMigration zu erstellen.

    • Fügen Sie hier die Auf- und Ab-Methode hinzu

RenameColumn ("yourDatabase", "name", "newName");

public override void Up()
  {
        RenameColumn("dbo.your_database", "oldColumn",          
       "newColumn");
  }


public override void Down()
  {
        RenameColumn("dbo.your_database", "newColumn", 
        "oldColumn");
  }

Denn wenn Sie eine Verbindung herstellen, kommunizieren Ihre Datenbank- und Modellklasse über name_column in der Datenbank und name_type in der Eigenschaftsmethode im obigen Modell.

Thảo Frederic
quelle
3

Zu Josh Gallaghers Antwort hinzufügen:

An einigen Stellen wird die sp_RENAME-Syntax folgendermaßen beschrieben:

sp_RENAME 'TableName.[OldColumnName]' , '[NewColumnName]', 'COLUMN'

Dies schließt jedoch tatsächlich die Klammern in den neuen Spaltennamen ein.

Die RenameColumn () -Methode von DbMigration wird wahrscheinlich dasselbe tun. Vermeiden Sie daher die Verwendung von Klammern, wenn Sie den neuen Spaltennamen angeben.

Zu den automatisch generierten Befehlen in Up () & Down () gehören DropPrimaryKey () und AddPrimaryKey (), wenn die umbenannte Spalte Teil des Primärschlüssels ist. Diese werden bei Verwendung von RenameColumn () nicht benötigt. Der zugrunde liegende sp_RENAME aktualisiert den Primärschlüssel bei Bedarf automatisch.

jk7
quelle
1

Wenn Sie in Entity Framework Core 3.1.1 eine Spalte umbenennen müssen, fügen Sie die Migration wie folgt hinzu

migrationBuilder.RenameColumn(
                                name: "oldname",
                                table: "tablename",
                                newName: "newname",
                                schema: "schema");
Ishika Jain
quelle
0

Wie + Josh Gallagher sagte, können Sie up () verwenden, um Dinge zu tun wie:

public override void Up()
        {

            RenameColumn("dbo.atable","oldname","newname");
            AddColumn("dbo.anothertable", "columname", c => c.String(maxLength: 250));

        }

Ich habe festgestellt, dass dies eine gute Hilfe ist, um in die Migration einzusteigen;)

Frau
quelle