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?

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.


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");
        }
    }
}

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 .


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


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.


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.


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");

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;)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.