在不丢弃数据的情况下重命名Entity Framework Core中的外键

时间:2018-04-12 14:48:43

标签: c# sql-server entity-framework entity-framework-core ef-core-2.0

我有两个模型类:

public class Survey
{
    public int SurveyId { get; set; }
    public string Name { get; set; }
}

public class User
{
    public int UserId { get; set; }

    public int SurveyId { get; set; }
    public Survey Survey { get; set; }
}

我想将Survey重命名为StudentSurvey,因此它会StudentSurveyId。我相应地更新了模型中的类名和属性,并添加了一个迁移。

但是,我得到了:

  

ALTER TABLE语句与FOREIGN KEY约束冲突" FK_User_Surveys_SurveyId"。冲突发生在数据库" AppName",table" dbo.Survey",column' SurveyId'。

我认为它试图删除数据,因为它需要列中的数据(不能为空)我看到了这个错误。但我不想丢弃数据。我怎样才能重命名呢?

2 个答案:

答案 0 :(得分:10)

EF Core将实体类重命名为删除旧实体并添加新实体,因此生成迁移以删除原始表并创建新表。

解决方法需要执行以下步骤:

(1)在重命名实体之前,使用HasColumnName[Table("StudentSurveys")] public class Survey { [Column("StudentSurveyId")] public int SurveyId { get; set; } public string Name { get; set; } } public class User { public int UserId { get; set; } [Column("StudentSurveyId")] public int SurveyId { get; set; } public Survey Survey { get; set; } } 流畅的API或数据注释“重命名”表和PK列。对引用该实体的FK列也执行相同操作。

例如:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropForeignKey(
        name: "FK_Users_Surveys_SurveyId",
        table: "Users");

    migrationBuilder.DropPrimaryKey(
        name: "PK_Surveys",
        table: "Surveys");

    migrationBuilder.RenameTable(
        name: "Surveys",
        newName: "StudentSurveys");

    migrationBuilder.RenameColumn(
        name: "SurveyId",
        table: "Users",
        newName: "StudentSurveyId");

    migrationBuilder.RenameIndex(
        name: "IX_Users_SurveyId",
        table: "Users",
        newName: "IX_Users_StudentSurveyId");

    migrationBuilder.RenameColumn(
        name: "SurveyId",
        table: "StudentSurveys",
        newName: "StudentSurveyId");

    migrationBuilder.AddPrimaryKey(
        name: "PK_StudentSurveys",
        table: "StudentSurveys",
        column: "StudentSurveyId");

    migrationBuilder.AddForeignKey(
        name: "FK_Users_StudentSurveys_StudentSurveyId",
        table: "Users",
        column: "StudentSurveyId",
        principalTable: "StudentSurveys",
        principalColumn: "StudentSurveyId",
        onDelete: ReferentialAction.Cascade);
}

(2)添加新迁移。它将正确地重命名表,PK列,FK列和相关约束:

public class StudentSurvey
{
    public int StudentSurveyId { get; set; }
    public string Name { get; set; }
}

public class User
{
    public int SurveyUserId { get; set; }
    public int StudentSurveyId { get; set; }
    public StudentSurvey StudentSurvey { get; set; }
}

(3)删除注释/流畅配置并执行实际的类/属性重命名:

DbSet

重命名相应的public DbSet<StudentSurvey> StudentSurveys { get; set; } (如果有):

Up

你完成了。

您可以通过添加新的迁移来验证它 - 它将采用空的DownIn [120]: df[df.days_old > 3]['fruit'].value_counts() Out[120]: apple 2 orange 1 Name: fruit, dtype: int64 方法。

答案 1 :(得分:1)

documentation 建议使用 MigrationBuilder.RenameColumn()。还有 RenameIndex()RenameTable() 和存储过程“sp_rename”(在 SQL Server 中)用于重命名外键。例如:

migrationBuilder.Sql($"EXEC sp_rename 'dbo.{oldName}', '{newName}'");

使用 SQL Server Management Studio 中的数据库脚本工具(rt-click DB | Tasks | Generate Scripts...)生成架构脚本,有和没有 EF 迁移自定义< /strong>,可以比较。然后你就会知道 EF 命名被保留了。

编辑:添加了“EXEC ...”以支持生成独立的 T-SQL 脚本