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