65

我重命名了一对夫妇实体及其导航属性,并在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.ReportPages的外键列从Group_Id重命名为Section_Id

我在删除将表连接在一起的外键和索引,然后我重命名表和外键列,然后再次添加索引和外键。我认为这是工作,但我得到一个SQL错误。

消息15248,级别11,状态1,过程sp_rename可以,215线 要么参数@objname不明确或所要求保护的@objtype(列)是错误的。 Msg 4902,Level 16,State 1,Line 10 找不到对象“dbo.ReportSections”,因为它不存在或您没有权限。

我没有一个容易的时间搞清楚这里有什么问题。任何见解都将非常有帮助。

+0

了上述线路的失败?你能跟踪SQL Server Profiler中的迁移并检查相应的SQL吗? –

回答

93

没关系。我正在使这种方式比它真正需要的更复杂。

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

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

请注意表中有点的表名。 'RenameColumn'生成一个'sp_rename' T-SQL语句,它在内部使用'parsename',它有一些限制。所以如果你有一个表名,里面有点, “SubSystemA.Tablename”然后使用:'RenameColumn(“dbo。[SubSystemA.Tablename]”,“OldColumnName”,“NewColumnName”);' – Ilan

+3

这似乎更新外键引用的列,但它不重命名FK本身。这是一种耻辱,但可能不是世界末日,除非你完全需要在后面提及它的名字。 – mikesigs

+6

@mikesigs你可以在你的迁移中使用'RenameIndex(..)'来重命名它 – JoeBrockhaus

2

我只是想在EF6相同(代码第一个实体命名)。我只是重命名了这个类,并使用包管理器控制台添加了一个迁移,并且使用RenameTable(...)进行迁移是我自动生成的。我不得不承认,我确信实体的唯一更改是重命名它,所以没有新列或重命名列,所以我不能确定这是EF6的事情还是只是EF(总是)能够检测到这种简单的迁移。

+0

我可以用6.1.3来确认这一点它确实正确地重命名表(不要忘记在'DatabaseContext'中重命名'DbSet'以及)。更改主键确实会造成麻烦。迁移将尝试删除它并创建一个新的。所以你需要调整它,并按照Chev的回答做,重命名列。 – CularBytes

15

如果你不喜欢写/在迁移类手动更改所需的代码,你可以按照两步走的方法,其自动进行所需要的RenameColumn代码:

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

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

步骤二更改属性名称,然后再次申请同一迁移(如Add-Migration ColumnChanged)在Package Manager控制台

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

如果你看一下移民类,你可以看到生成的自动代码为RenameColumn

3

要扩大一点Hossein Narimani Rad的答案,您可以使用系统重命名表和列。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); 
    }