C# EFCore回滚迁移错误:用作键列的列类型无效

C# EFCore回滚迁移错误:用作键列的列类型无效,c#,entity-framework,ef-core-2.0,C#,Entity Framework,Ef Core 2.0,我遇到了一个问题,我试图在已经应用了迁移的数据库上回滚迁移 这是我得到的错误: Failed executing DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] ALTER TABLE [EventStaffRequest] ADD CONSTRAINT [PK_EventStaffRequest] PRIMARY KEY ([Id]); System.Data.SqlClient.SqlExcep

我遇到了一个问题,我试图在已经应用了迁移的数据库上回滚迁移

这是我得到的错误:

Failed executing DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE [EventStaffRequest] ADD CONSTRAINT [PK_EventStaffRequest] PRIMARY KEY ([Id]);
System.Data.SqlClient.SqlException (0x80131904): Column 'Id' in table 'EventStaffRequest' is of a type that is invalid for use as a key column in an index.
Could not create constraint or index. See previous errors.

ClientConnectionId:29574816-2b1a-4490-a216-a54cd7a2d33b
Error Number:1919,State:1,Class:16
Column 'Id' in table 'EventStaffRequest' is of a type that is invalid for use as a key column in an index.
Could not create constraint or index. See previous errors.
这是我正在尝试回滚的迁移:

public partial class AddedCompositeKeyToEventStaffRequest : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropPrimaryKey(
            name: "PK_EventStaffRequest",
            table: "EventStaffRequest");

        migrationBuilder.DropIndex(
            name: "IX_EventStaffRequest_EventId",
            table: "EventStaffRequest");

        migrationBuilder.DropColumn(
            name: "Id",
            table: "EventStaffRequest");

        migrationBuilder.AddPrimaryKey(
            name: "PK_EventStaffRequest",
            table: "EventStaffRequest",
            columns: new[] { "EventId", "QualityTypeId" });
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropPrimaryKey(
            name: "PK_EventStaffRequest",
            table: "EventStaffRequest");

        migrationBuilder.AddColumn<string>(
            name: "Id",
            table: "EventStaffRequest",
            nullable: false,
            defaultValue: "");

        migrationBuilder.AddPrimaryKey(
            name: "PK_EventStaffRequest",
            table: "EventStaffRequest",
            column: "Id");

        migrationBuilder.CreateIndex(
            name: "IX_EventStaffRequest_EventId",
            table: "EventStaffRequest",
            column: "EventId");
    }
}
创建此迁移是因为我决定需要将主键更改为复合键。我已经在我的DbContext中应用了这样一个复合主键(这是您在迁移的
Up()
中看到的):

builder.Entity()
.HasKey(esr=>new{esr.EventId,esr.QualityTypeId});

为什么我的回滚没有成功?我不明白为什么
string
不是键索引的合适类型(我使用guid作为键)。

迁移系统似乎有问题。问题不在于
字符串
(当然它可以用于PK),而在于
maxLength
。默认情况下,
字符串
列的长度不受限制,但PK需要应用一些限制

通常,当您使用
string
列作为主键时,即使您没有指定
maxLength
,EF也会自动应用一些限制(据我所见,至少对于SqlServer而言,它是
450
)。有趣的是,以相反的顺序执行相同的操作会生成类似的迁移,其中
向上
向下
内容交换,并且
AddColumn
的代码完全相同。但在
Down
方法中执行时不会,因此该路径中肯定存在差异(因此存在问题)。你可以考虑把它放在EF核心问题跟踪器中,这样他们就知道了(最终修复它)。 无论如何,解决方案是显式地将
maxLength
参数添加到
AddColumn
调用:

migrationBuilder.AddColumn<string>(
    name: "Id",
    table: "EventStaffRequest",
    maxLength: 450,
    nullable: false,
    defaultValue: "");
migrationBuilder.AddColumn(
姓名:“Id”,
表:“EventStaffRequest”,
最大长度:450,
可为空:false,
默认值:“”);

您能否在不可为空的PK上设置默认值?你的表格里有数据吗?除非该表为空,否则无法在具有所有相同默认值的列上创建PK…很可能需要将
maxLength:some_值添加到
AddColumn(…)
(长度不限的字符串不能用作PK)。但是您还需要用唯一的数据填充列,否则
AddPrimaryKey
将失败。一般来说,这种导致数据丢失的迁移(通过删除列)是不可逆的。@oerlekens如果EventStaffRequest表为空,则在回滚迁移之前,我已删除了所有记录。我尝试在迁移中设置
defaultvalue=Guid.NewGuid().ToString()
,但遗憾的是,这并没有改变任何事情。@IvanStoev谢谢,这就解决了问题。我添加了
maxLength:100
,现在可以很好地回滚迁移。谢谢数据丢失对我来说不是问题,该项目仍在开发中,但我正在努力回滚数据库以切换到另一个功能分支。请随意发表你的评论作为回答,我会接受的。
builder.Entity<EventStaffRequest>()
    .HasKey(esr => new { esr.EventId, esr.QualityTypeId });
migrationBuilder.AddColumn<string>(
    name: "Id",
    table: "EventStaffRequest",
    maxLength: 450,
    nullable: false,
    defaultValue: "");