65

Ich habe ein paar Entitäten und deren Navigationseigenschaften umbenannt und eine neue Migration in EF 5 generiert. Wie bei Umbenennungen in EF-Migrationen üblich, wurden Objekte standardmäßig gelöscht und neu erstellt. Das wollte ich nicht, also musste ich die Migrationsdatei von Grund auf neu erstellen.Entity Framework Migrationen Umbenennen von Tabellen und Spalten

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

Alles, was ich versuche zu tun, umbenennen dbo.ReportSections-dbo.ReportPages und dann dbo.ReportSectionGroups zu dbo.ReportSections. Dann muss ich die Fremdschlüsselspalte unter dbo.ReportPages von Group_Id zu Section_Id umbenennen.

Ich lasse die Fremdschlüssel und Indizes, die die Tabellen verbinden, fallen, dann benenne ich die Tabellen und die Fremdschlüsselspalte, dann füge ich die Indizes und Fremdschlüssel wieder hinzu. Ich nahm an, dass dies funktionieren würde, aber ich bekomme einen SQL-Fehler.

Msg 15248, Ebene 11, Status 1, Prozedur sp_rename, Leitung 215 Entweder der Parameter @objname mehrdeutig oder das beanspruchte @objtype (Spalte) ist falsch. Msg 4902, Ebene 16, Status 1, Zeile 10 Das Objekt "dbo.ReportSections" kann nicht gefunden werden, da es nicht existiert oder Sie keine Berechtigungen haben.

Ich habe keine leichte Zeit herauszufinden, was hier falsch ist. Jede Einsicht wäre ungeheuer hilfreich.

+0

Welche der obigen Zeilen ausfällt? Können Sie die Migration in SQL Server Profiler verfolgen und die entsprechende SQL überprüfen? –

Antwort

93

Vergesst nicht. Ich machte diesen Weg komplizierter, als es wirklich sein musste.

Das war alles was ich brauchte. Die Umbenennungsmethoden erzeugen nur einen Aufruf an die Systemprozedur sp_rename, und ich nehme an, dass sich um alles gekümmert hat, einschließlich der Fremdschlüssel mit dem neuen Spaltennamen.

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

Seien Sie vorsichtig mit Tabellennamen, die Punkte enthalten. 'RenameColumn' erzeugt eine' sp_rename' T-SQL-Anweisung, die intern 'parsename' verwendet, die einige Einschränkungen aufweist. Wenn Sie also einen Tabellennamen mit Punkten haben, z. "SubSystemA.Tabelname" verwendet dann: 'RenameColumn (" dbo. [SubSystemA.Tabelname] "," OldColumnName "," NewColumnName ");' – Ilan

+3

Dies scheint die Spalten zu aktualisieren, auf die in den Fremdschlüsseln verwiesen wird, aber die FK selbst. Was schade ist, aber wahrscheinlich nicht das Ende der Welt, es sei denn, Sie müssen unbedingt später auf einen FK mit seinem Namen verweisen. – mikesigs

+6

@Mikesigs können Sie 'RenameIndex (..)' in Ihrer Migration verwenden, um es umzubenennen – JoeBrockhaus

2

Ich habe gerade das gleiche in EF6 (Code erste Entity umbenennen) versucht. Ich habe die Klasse einfach umbenannt und eine Migration über die Paketmanager-Konsole und voila hinzugefügt. Eine Migration mit RenameTable (...) wurde automatisch für mich generiert. Ich muss zugeben, dass ich dafür gesorgt habe, dass die einzige Änderung an der Entity darin umbenannt wurde, also keine neuen Spalten oder umbenannten Spalten, so dass ich nicht sicher sein kann, ob dies eine EF6-Sache ist oder EF einfach (immer) solche einfachen Migrationen erkennen kann.

+0

Ich kann dies mit 6.1.3 bestätigen. Es benennt die Tabelle korrekt um (vergessen Sie nicht, 'DbSet' in Ihrem' DatabaseContext' umzubenennen auch). Das Ändern des Primärschlüssels verursacht Probleme. Die Migration versucht, sie zu löschen und eine neue zu erstellen. Also müssen Sie das anpassen und tun, wie Chev's Antwort ist, benennen Sie die Spalte um. – CularBytes

15

Wenn Sie nicht wie das Schreiben/Ändern den erforderlichen Code in der Migration Klasse manuell, können Sie einen zweistufigen Ansatz folgen, die automatisch den RenameColumn Code vornehmen, die erforderlich ist:

Step One Verwenden ColumnAttribute die neuen Spaltennamen einzuführen und dann Add-Migration (zB Add-Migration ColumnChanged)

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

Step-Two die Eigenschaftsnamen ändern und gilt wieder auf gleiche Migration (zB Add-Migration ColumnChanged) im Paket-Manager-Konsole

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

Wenn Sie bei der Migration Klasse schauen, können Sie die automatisch generierten Code sehen RenameColumn ist.

3

Um ein wenig auf die Antwort von Hossein Narimani Rad zu erweitern, können Sie sowohl eine Tabelle als auch Spalten mit System umbenennen.ComponentModel.DataAnnotations.Schema.TableAttribute bzw. System.ComponentModel.DataAnnotations.Schema.ColumnAttribute.

dies ein paar Vorteile:

  1. Dies wird nicht nur erstellen, die die Namen Migrationen automatisch, aber
  2. es wird auch köstlich keine Fremdschlüssel löschen und sie gegen die neuen Tabellen- und Spaltennamen neu erstellen, die Fremdschlüssel geben und die Eigennamen verdichten.
  3. All dies ohne Tabellendaten
  4. zu verlieren

Zum Beispiel das Hinzufügen [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; } 
} 

Wird die Migration generieren:

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