Entity Framework 마이그레이션 테이블 및 열 이름 바꾸기


118

몇 개의 엔터티와 해당 탐색 속성의 이름을 변경하고 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_IdSection_Id.

테이블을 함께 연결하는 외래 키와 인덱스를 삭제하고 테이블과 외래 키 열의 이름을 바꾼 다음 인덱스와 외래 키를 다시 추가합니다. 이것이 작동 할 것이라고 생각했지만 SQL 오류가 발생합니다.

Msg 15248, 수준 11, 상태 1, 프로 시저 sp_rename, 줄 215 @objname 매개 변수가 모호하거나 요청 된 @objtype (COLUMN)이 잘못되었습니다. Msg 4902, 수준 16, 상태 1, 줄 10 "dbo.ReportSections"개체가 없거나 권한이 없기 때문에 찾을 수 없습니다.

나는 여기서 무엇이 잘못되었는지 쉽게 알 수 없습니다. 어떤 통찰력이라도 엄청나게 도움이 될 것입니다.


위의 줄 중 어떤 것이 실패합니까? SQL Server Profiler에서 마이그레이션을 추적하고 해당 SQL을 확인할 수 있습니까?
Albin Sunnanbo 2012

답변:


143

신경 쓰지 마. 나는이 방법을 정말로 필요했던 것보다 더 복잡하게 만들고 있었다.

이것이 내가 필요한 전부였습니다. rename 메서드는 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");
}

29
점이있는 테이블 이름에주의하십시오. 내부적으로 사용 RenameColumn하는 sp_renameT-SQL 문을 생성하며 parsename일부 제한이 있습니다. 따라서 "SubSystemA.Tablename"과 같이 점이있는 테이블 이름이있는 경우 다음을 사용하십시오.RenameColumn("dbo.[SubSystemA.Tablename]", "OldColumnName", "NewColumnName");
Ilan

10
이것은 외래 키에서 참조되는 열을 업데이트하는 것처럼 보이지만 FK 자체의 이름을 바꾸지는 않습니다. 부끄러운 일이지만 나중에 FK 이름을 절대적으로 참조해야하는 경우가 아니면 세상의 끝은 아닐 것입니다.
mikesigs

9
@mikesigs 당신이 사용할 수있는 RenameIndex(..)이름을 변경하는 마이그레이션에
JoeBrockhaus

1
열 이름을 바꿀 때 예외가 발생합니다. 이름 바꾸기 테이블이 아직 적용되지 않았기 때문일 수 있습니다. 나는 두 마이그레이션로를 분할했다
여호수아 마르티네즈에게

EF6에서는 RenameTable(..)FK와 PK의 이름을 바꾸는 데 사용 합니다. 옳은 소리는 아니지만 그것은 나를 위해 일한 것입니다. 올바른 T-SQL ( execute sp_rename ...) 을 만드는 방법입니다 . update-database -verbose를 수행하면 직접 볼 수 있습니다.
Giovanni

44

Migration 클래스에서 필요한 코드를 수동으로 작성 / 변경하는 것을 좋아하지 않는 경우 필요한 코드를 자동으로 만드는 2 단계 접근 방식을 따를 수 있습니다 RenameColumn.

단계 중 하나 를 사용하여이 ColumnAttribute추가 마이그레이션 한 후 (예를 새로운 열 이름을 소개합니다 Add-Migration ColumnChanged)

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

2 단계 : 속성 이름을 변경 Add-Migration ColumnChanged -force하고 패키지 관리자 콘솔에서 동일한 마이그레이션 (예 :)에 다시 적용

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

Migration 클래스를 보면 자동으로 생성 된 코드가 RenameColumn.


동일한 마이그레이션을 어떻게 두 번 추가 할 수 있습니까? 나는이 때, 내가 얻을 :The name 'Rename_SalesArea' is used by an existing migration.
앤드류 S

한 번 봐 가지고 -force추가 마이그레이션을 사용하는 경우 매개 변수를
호세인 Narimani 라드에게

2
이 게시물 EF 코어위한 것이 아닙니다주의
호세인 Narimani 라드

6
마이그레이션은 하나만 필요하지만 여전히 두 단계가 필요합니다. 1. 속성을 추가하고 "마이그레이션 이름 변경"을 생성합니다. 2. 속성 이름 만 변경하면됩니다. 그게 다야. 어느 쪽이든, 이것은 저에게 엄청난 시간을 절약했습니다. 감사!
Crispy Ninja

1
여기에 언급 된 단계를 따랐고 성공적이었습니다. 기존 데이터를 잃지 않았습니다. 내가 정말로 원했던 것은 데이터 손실없이 변경하는 것입니다. 그러나 안전한 측면을 위해 클래스의 속성 이름을 바꾼 후 다른 마이그레이션을 실행합니다.
Manojb86

19

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

1
테이블 속성을 추가하는 것이 기본값이어야하는 것처럼 보이므로 작업이 훨씬 간단 해집니다.
patrick

17

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

3

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

2

방금 EF6에서 똑같이 시도했습니다 (코드 첫 번째 엔티티 이름 바꾸기). 나는 단순히 클래스의 이름을 바꾸고 패키지 관리자 콘솔을 사용하여 마이그레이션을 추가했으며 RenameTable (...)을 사용하는 마이그레이션이 자동으로 생성되었습니다. 나는 엔티티에 대한 유일한 변경이 새 열이나 이름이 변경된 열이 없도록 이름을 바꾸는 것이 었음을 인정해야하므로 이것이 EF6인지 또는 EF가 (항상) 그러한 간단한 마이그레이션을 감지 할 수 있는지 확신 할 수 없습니다.


2
내가 뭔가를 제대로 테이블의 이름을 변경 않습니다 6.1.3로 이것을 확인할 수 있습니다합니다 (이름을 변경하는 것을 잊지 마세요 DbSet당신에 DatabaseContext뿐만 아니라). 기본 키를 변경하면 문제가 발생합니다. 마이그레이션은이를 삭제하고 새 항목을 작성하려고합니다. 그래서 당신은 그것을 조정하고 Chev의 대답처럼 열 이름을 변경해야합니다.
CularBytes 2016-06-28

1

테이블 이름과 열 이름은의 매핑의 일부로 지정할 수 있습니다 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");
            });
     }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.