144

我重命名了一对实体及其导航属性,并在 EF 5 中生成了一个新的迁移。与 EF 迁移中的重命名一样,默认情况下它会删除对象并重新创建它们。这不是我想要的,所以我几乎不得不从头开始构建迁移文件。

    public override void Up()
    {
        DropForeignKey("dbo.ReportSectionGroups", "Report_Id", "dbo.Reports");
        DropForeignKey("dbo.ReportSections", "Group_Id", "dbo.ReportSectionGroups");
        DropForeignKey("dbo.Editables", "Section_Id", "dbo.ReportSections");
        DropIndex("dbo.ReportSectionGroups", new[] { "Report_Id" });
        DropIndex("dbo.ReportSections", new[] { "Group_Id" });
        DropIndex("dbo.Editables", new[] { "Section_Id" });

        RenameTable("dbo.ReportSections", "dbo.ReportPages");
        RenameTable("dbo.ReportSectionGroups", "dbo.ReportSections");
        RenameColumn("dbo.ReportPages", "Group_Id", "Section_Id");

        AddForeignKey("dbo.ReportSections", "Report_Id", "dbo.Reports", "Id");
        AddForeignKey("dbo.ReportPages", "Section_Id", "dbo.ReportSections", "Id");
        AddForeignKey("dbo.Editables", "Page_Id", "dbo.ReportPages", "Id");
        CreateIndex("dbo.ReportSections", "Report_Id");
        CreateIndex("dbo.ReportPages", "Section_Id");
        CreateIndex("dbo.Editables", "Page_Id");
    }

    public override void Down()
    {
        DropIndex("dbo.Editables", "Page_Id");
        DropIndex("dbo.ReportPages", "Section_Id");
        DropIndex("dbo.ReportSections", "Report_Id");
        DropForeignKey("dbo.Editables", "Page_Id", "dbo.ReportPages");
        DropForeignKey("dbo.ReportPages", "Section_Id", "dbo.ReportSections");
        DropForeignKey("dbo.ReportSections", "Report_Id", "dbo.Reports");

        RenameColumn("dbo.ReportPages", "Section_Id", "Group_Id");
        RenameTable("dbo.ReportSections", "dbo.ReportSectionGroups");
        RenameTable("dbo.ReportPages", "dbo.ReportSections");

        CreateIndex("dbo.Editables", "Section_Id");
        CreateIndex("dbo.ReportSections", "Group_Id");
        CreateIndex("dbo.ReportSectionGroups", "Report_Id");
        AddForeignKey("dbo.Editables", "Section_Id", "dbo.ReportSections", "Id");
        AddForeignKey("dbo.ReportSections", "Group_Id", "dbo.ReportSectionGroups", "Id");
        AddForeignKey("dbo.ReportSectionGroups", "Report_Id", "dbo.Reports", "Id");
    }

我要做的就是重命名dbo.ReportSectionsdbo.ReportPages,然后重命名dbo.ReportSectionGroupsdbo.ReportSections. 然后我需要将外键列重命名为dbo.ReportPagesfrom Group_Idto Section_Id

我删除将表链接在一起的外键和索引,然后重命名表和外键列,然后再次添加索引和外键。我以为这会起作用,但我收到了一个 SQL 错误。

消息 15248,级别 11,状态 1,过程 sp_rename,第 215 行参数 @objname 不明确或声明的 @objtype (COLUMN) 错误。消息 4902,级别 16,状态 1,第 10 行找不到对象“dbo.ReportSections”,因为它不存在或您没有权限。

我很难弄清楚这里出了什么问题。任何见解都会非常有帮助。

4

8 回答 8

173

没关系。我让这种方式变得比它真正需要的更复杂。

这就是我所需要的。重命名方法只是生成对sp_rename系统存储过程的调用,我猜这会处理所有事情,包括具有新列名的外键。

public override void Up()
{
    RenameTable("ReportSections", "ReportPages");
    RenameTable("ReportSectionGroups", "ReportSections");
    RenameColumn("ReportPages", "Group_Id", "Section_Id");
}

public override void Down()
{
    RenameColumn("ReportPages", "Section_Id", "Group_Id");
    RenameTable("ReportSections", "ReportSectionGroups");
    RenameTable("ReportPages", "ReportSections");
}
于 2012-11-08T20:27:43.730 回答
61

如果您不喜欢手动编写/更改 Migration 类中所需的代码,您可以按照两步方法自动RenameColumn生成所需的代码:

第一步使用ColumnAttribute引入新的列名,然后添加迁移(例如Add-Migration ColumnChanged

public class ReportPages
{
    [Column("Section_Id")]                 //Section_Id
    public int Group_Id{get;set}
}

第二步更改属性名称并再次应用于Add-Migration ColumnChanged -force包管理器控制台中的相同迁移(例如)

public class ReportPages
{
    [Column("Section_Id")]                 //Section_Id
    public int Section_Id{get;set}
}

如果您查看 Migration 类,您可以看到自动生成的代码是RenameColumn.

于 2016-07-23T07:40:19.720 回答
39

在 EF Core 中,我使用以下语句重命名表和列:

至于重命名表:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameTable(
            name: "OldTableName",
            schema: "dbo",
            newName: "NewTableName",
            newSchema: "dbo");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameTable(
            name: "NewTableName",
            schema: "dbo",
            newName: "OldTableName",
            newSchema: "dbo");
    }

至于重命名列:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: "OldColumnName",
            table: "TableName",
            newName: "NewColumnName",
            schema: "dbo");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(
            name: "NewColumnName",
            table: "TableName",
            newName: "OldColumnName",
            schema: "dbo");
    }
于 2018-06-16T08:16:16.047 回答
27

要扩展 Hossein Narimani Rad 的答案,您可以分别使用 System.ComponentModel.DataAnnotations.Schema.TableAttribute 和 System.ComponentModel.DataAnnotations.Schema.ColumnAttribute 重命名表和列。

这有几个好处:

  1. 这不仅会自动创建名称迁移,而且
  2. 它还将很好地删除任何外键并根据新的表和列名重新创建它们,为外键和容器提供正确的名称。
  3. 所有这些都不会丢失任何表数据

例如,添加[Table("Staffs")]

[Table("Staffs")]
public class AccountUser
{
    public long Id { get; set; }

    public long AccountId { get; set; }

    public string ApplicationUserId { get; set; }

    public virtual Account Account { get; set; }

    public virtual ApplicationUser User { get; set; }
}

将生成迁移:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_AccountUsers_Accounts_AccountId",
            table: "AccountUsers");

        migrationBuilder.DropForeignKey(
            name: "FK_AccountUsers_AspNetUsers_ApplicationUserId",
            table: "AccountUsers");

        migrationBuilder.DropPrimaryKey(
            name: "PK_AccountUsers",
            table: "AccountUsers");

        migrationBuilder.RenameTable(
            name: "AccountUsers",
            newName: "Staffs");

        migrationBuilder.RenameIndex(
            name: "IX_AccountUsers_ApplicationUserId",
            table: "Staffs",
            newName: "IX_Staffs_ApplicationUserId");

        migrationBuilder.RenameIndex(
            name: "IX_AccountUsers_AccountId",
            table: "Staffs",
            newName: "IX_Staffs_AccountId");

        migrationBuilder.AddPrimaryKey(
            name: "PK_Staffs",
            table: "Staffs",
            column: "Id");

        migrationBuilder.AddForeignKey(
            name: "FK_Staffs_Accounts_AccountId",
            table: "Staffs",
            column: "AccountId",
            principalTable: "Accounts",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

        migrationBuilder.AddForeignKey(
            name: "FK_Staffs_AspNetUsers_ApplicationUserId",
            table: "Staffs",
            column: "ApplicationUserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_Staffs_Accounts_AccountId",
            table: "Staffs");

        migrationBuilder.DropForeignKey(
            name: "FK_Staffs_AspNetUsers_ApplicationUserId",
            table: "Staffs");

        migrationBuilder.DropPrimaryKey(
            name: "PK_Staffs",
            table: "Staffs");

        migrationBuilder.RenameTable(
            name: "Staffs",
            newName: "AccountUsers");

        migrationBuilder.RenameIndex(
            name: "IX_Staffs_ApplicationUserId",
            table: "AccountUsers",
            newName: "IX_AccountUsers_ApplicationUserId");

        migrationBuilder.RenameIndex(
            name: "IX_Staffs_AccountId",
            table: "AccountUsers",
            newName: "IX_AccountUsers_AccountId");

        migrationBuilder.AddPrimaryKey(
            name: "PK_AccountUsers",
            table: "AccountUsers",
            column: "Id");

        migrationBuilder.AddForeignKey(
            name: "FK_AccountUsers_Accounts_AccountId",
            table: "AccountUsers",
            column: "AccountId",
            principalTable: "Accounts",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

        migrationBuilder.AddForeignKey(
            name: "FK_AccountUsers_AspNetUsers_ApplicationUserId",
            table: "AccountUsers",
            column: "ApplicationUserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }
于 2017-05-31T02:16:51.587 回答
2

我刚刚在 EF6 中尝试了相同的操作(代码优先实体重命名)。我只是重命名了该类并使用包管理器控制台添加了一个迁移,瞧,使用 RenameTable(...) 的迁移是自动为我生成的。我必须承认,我确保对实体的唯一更改是重命名它,因此没有新列或重命名列,所以我无法确定这是 EF6 的事情还是只是 EF (总是)能够检测到如此简单的迁移。

于 2015-12-21T11:42:51.947 回答
2

表名和列名可以指定为 的映射的一部分DbContext。那么在迁移中就不需要这样做了。

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Restaurant>()
            .HasMany(p => p.Cuisines)
            .WithMany(r => r.Restaurants)
            .Map(mc =>
            {
                mc.MapLeftKey("RestaurantId");
                mc.MapRightKey("CuisineId");
                mc.ToTable("RestaurantCuisines");
            });
     }
}
于 2018-05-07T08:26:25.383 回答
2

在 ef core 中,您可以更改添加迁移后创建的迁移。然后做更新数据库。下面给出了一个示例:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.RenameColumn(name: "Type", table: "Users", newName: "Discriminator", schema: "dbo");
}

protected override void Down(MigrationBuilder migrationBuilder)
{            
    migrationBuilder.RenameColumn(name: "Discriminator", table: "Users", newName: "Type", schema: "dbo");
}
于 2019-09-08T10:33:10.810 回答
2

对于 EF CoremigrationBuilder.RenameColumn通常可以正常工作,但有时您也必须处理索引。

migrationBuilder.RenameColumn(name: "Identifier", table: "Questions", newName: "ChangedIdentifier", schema: "dbo");

更新数据库时的示例错误消息:

Microsoft.Data.SqlClient.SqlException (0x80131904):索引“IX_Questions_Identifier”依赖于“标识符”列。

索引“IX_Questions_Identifier”取决于“标识符”列。

重命名列标识符失败,因为一个或多个对象访问此列。

在这种情况下,您必须像这样进行重命名:

migrationBuilder.DropIndex(
    name: "IX_Questions_Identifier",
    table: "Questions");

migrationBuilder.RenameColumn(name: "Identifier", table: "Questions", newName: "ChangedIdentifier", schema: "dbo");

migrationBuilder.CreateIndex(
    name: "IX_Questions_ChangedIdentifier",
    table: "Questions",
    column: "ChangedIdentifier",
    unique: true,
    filter: "[ChangedIdentifier] IS NOT NULL");
于 2020-10-15T11:48:55.860 回答