Pregunta Migraciones de Entity Framework cambiando el nombre de las tablas y columnas


Cambié el nombre a un par de entidades y sus propiedades de navegación y generé una nueva Migración en EF 5. Como es habitual con los cambios de nombre en las migraciones de EF, de forma predeterminada iba a soltar objetos y recrearlos. Eso no es lo que quería, así que tuve que construir el archivo de migración desde cero.

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

Todo lo que intento hacer es cambiar el nombre dbo.ReportSections a dbo.ReportPages y entonces dbo.ReportSectionGroups a dbo.ReportSections. Entonces necesito cambiar el nombre de la columna de clave externa en dbo.ReportPages de Group_Id a Section_Id.

Estoy eliminando las claves externas y los índices que vinculan las tablas, luego cambio el nombre de las tablas y la columna de la clave externa, y luego vuelvo a agregar los índices y las claves externas. Supuse que esto iba a funcionar, pero estoy recibiendo un error de SQL.

Msg 15248, nivel 11, estado 1, procedimiento nombre_re, línea 215   O el parámetro @objname es ambiguo o el @objtype reclamado (COLUMN) es incorrecto.   Msg 4902, nivel 16, estado 1, línea 10   No se puede encontrar el objeto "dbo.ReportSections" porque no existe o no tiene permisos.

No me es fácil descifrar qué está mal aquí. Cualquier idea sería tremendamente útil.


76
2017-11-08 20:12


origen


Respuestas:


No importa. Estaba haciendo esto de una manera más complicada de lo que realmente necesitaba ser.

Esto era todo lo que necesitaba. Los métodos de cambio de nombre solo generan una llamada al sp_rename sistema de procedimiento almacenado y supongo que se hizo cargo de todo, incluidas las claves externas con el nuevo nombre de columna.

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

108
2017-11-08 20:27



Si no le gusta escribir / cambiar el código requerido en la clase Migration manualmente, puede seguir un enfoque en dos pasos que automáticamente hace que el RenameColumn código que se requiere:

Paso uno Utilizar el ColumnAttribute para introducir el nuevo nombre de columna y luego agregar-migración (p. Add-Migration ColumnChanged)

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

Segundo paso cambiar el nombre de la propiedad y volver a aplicar a la misma migración (p. Add-Migration ColumnChanged) en la consola del administrador de paquetes

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

Si miras la clase de Migración, puedes ver que el código generado automáticamente es RenameColumn.


19
2017-07-23 07:40



Para ampliar un poco la respuesta de Hossein Narimani Rad, puede cambiar el nombre de una tabla y columnas usando System.ComponentModel.DataAnnotations.Schema.TableAttribute y System.ComponentModel.DataAnnotations.Schema.ColumnAttribute, respectivamente.

Esto tiene un par de beneficios:

  1. Esto no solo creará el nombre de migraciones automáticamente, sino que
  2. también borrará deliciosamente las claves foráneas y las volverá a crear contra los nuevos nombres de tabla y columna, dando a las claves foráneas y a los constantes nombres propios.
  3. Todo esto sin perder ningún dato de tabla

Por ejemplo, agregar [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; }
}

Generará la migración:

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

6
2018-05-31 02:16



Acabo de probar lo mismo en EF6 (renombra el primer nombre de la entidad). Simplemente renombré la clase y agregué una migración usando la consola del administrador de paquetes y voila, una migración usando RenameTable (...) se generó automáticamente para mí. Tengo que admitir que me aseguré de que el único cambio en la entidad fuera cambiarle el nombre para que no haya nuevas columnas o columnas renombradas, así que no puedo estar seguro si esto es algo de EF6 o simplemente que EF fue (siempre) capaz de detectar tales migraciones simples.


2
2017-12-21 11:42



En EF Core (2.0), utilizo las siguientes declaraciones para cambiar el nombre de tablas y columnas:

En cuanto a renombrar tablas:

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

En cuanto a cambiar el nombre de las columnas:

    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: "Orders", newName: "OldColumnName", schema: "dbo");
    }

2
2018-06-16 08:16



Los nombres de tabla y columna se pueden especificar como parte del mapeo de DbContext. Entonces no hay necesidad de hacerlo en migraciones.

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

0
2018-05-07 08:26