如何在不丢失数据的情况下在Entity Framework 5 Code First迁移中重命名数据库列?


74

我获得了默认的ASP.NET MVC 4模板,该模板成功与EF 5.0代码优先迁移一起运行。但是,当我更新模型属性名称时,EF 5.0会删除相应的表列数据。

是否可以通过某种方式重命名表列而不自动删除数据?

Answers:


114

手动编辑迁移的“向上”和“向下”方法,以使用该RenameColumn方法替换AddColumnDropColumn为您自动生成的。


10
注意表名中带有点。RenameColumn生成一条sp_renameT-SQL语句,该语句在parsename内部使用use,这有一些限制。因此,如果您的表名中带有点,例如“ SubSystemA.Tablename”,则使用:RenameColumn("dbo.[SubSystemA.Tablename]", "OldColumnName", "NewColumnName");
Ilan,

我认为此答案假设您具有AutomaticMigration = true然后执行命令Add-Migration renameColumnXXX。之后,检查生成的迁移文件并删除DropColumnAddColum
JenonD

45

前面已经说了,更换AddColumnDropColumn自动与生成RenameColumn

例:

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

可以得到迁移打电话RenameColumn,如果你为你做这个:

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

这是生成的迁移:

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

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

如果希望属性和DB列具有相同的名称,则可以稍后重命名该属性并删除该Column属性。


1
只是抛出另一个有用的提示,您还可以在Package Manager Console中运行它Update-Database -Script。然后,您可以随意sp_rename运行SQL命令。:D
Jess

1
首选方法,因为还解决了模型的属性名称。并且我验证了重命名属性的可选第二步中生成了空迁移。
bvj

4

现在,此答案基于我对EF4.3的了解,所以我希望迁移在EF5中大致相同:)创建迁移后,您应该能够在Up和Down方法之间添加代码旧资产的删除和新资产的创建。此代码应沿正确的方向移动属性数据。我已经使用SQL()方法解决了该问题,您可以在其中输入原始SQL来执行数据移动。

在迁移的Up方法中:

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

并在Down()方法中:

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

这种方法的缺点是您可能会将代码与当前正在使用的数据库耦合(因为您正在编写原始的特定于DB的SQL)。可能还有其他方法可用于数据移动。

更多信息可在这里:MSDN


4

您有2个步骤可以在代码首次迁移时重命名列

  1. 第一步,在要更改的列上方添加ColumnAttribute,然后执行update-database命令

[Column(“ Content”)]
公共字符串说明{set; 得到; }

  1. 第二步

    • add-migration yournamechange命令以创建部分类DbMigration。

    • 在这里添加上下方法

RenameColumn(“ yourDatabase”,“ name”,“ newName”);

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


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

因为当您连接时,您的数据库和模型类将通过上述模型中数据库的name_column和name_type进行通信。


3

添加到乔什·加拉格尔的答案中:

在某些地方,像这样描述sp_RENAME语法:

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

但是,这实际上将在新列名称中包含方括号。

DbMigration的RenameColumn()方法可能会执行相同的操作,因此在指定新列名时避免使用方括号。

另外,如果要重命名的列是主键的一部分,则Up()和Down()中自动生成的命令包括DropPrimaryKey()和AddPrimaryKey()。使用RenameColumn()时不需要这些。如果需要,底层的sp_RENAME将自动更新主键。


2

Entity Framework Core 3.1.1中,如果需要重命名列-如下添加迁移

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

0

就像+ Josh Gallagher所说的那样,您可以使用up()做类似的事情:

public override void Up()
        {

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

        }

我发现对开始迁移很有帮助;)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.