更新 - 数据库失败:“索引'IX_Task_UserId'依赖于列'UserId'”

时间:2017-01-07 18:24:03

标签: asp.net asp.net-mvc entity-framework asp.net-core entity-framework-core

在3个模型的2个属性上添加[required]注释并运行add-migration后,运行update-database时出现以下错误。

ALTER TABLE ALTER COLUMN UserId failed because one or more objects access this column. The index 'IX_Task_UserId' is dependent on column 'UserId'.

我的up()迁移如下所示:

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

        migrationBuilder.DropForeignKey(
            name: "FK_Template_AspNetUsers_UserId",
            table: "Template");

        migrationBuilder.DropForeignKey(
            name: "FK_Task_AspNetUsers_UserId",
            table: "Task");

        migrationBuilder.AlterColumn<string>(
            name: "UserId",
            table: "Task",
            nullable: false);

        migrationBuilder.AlterColumn<string>(
            name: "TaskName",
            table: "Task",
            nullable: false);

        migrationBuilder.AlterColumn<string>(
            name: "UserId",
            table: "Template",
            nullable: false);

        migrationBuilder.AlterColumn<string>(
            name: "TemplateName",
            table: "Template",
            nullable: false);

        migrationBuilder.AlterColumn<string>(
            name: "UserId",
            table: "TaskList",
            nullable: false);

        migrationBuilder.AlterColumn<string>(
            name: "ListName",
            table: "TaskList",
            nullable: false);

        migrationBuilder.AddForeignKey(
            name: "FK_TaskList_AspNetUsers_UserId",
            table: "TaskList",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

        migrationBuilder.AddForeignKey(
            name: "FK_Template_AspNetUsers_UserId",
            table: "Template",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

        migrationBuilder.AddForeignKey(
            name: "FK_Task_AspNetUsers_UserId",
            table: "Task",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    }

我不确定错误所引用的索引,也不完全理解为什么删除外键(同样,我所做的只是使一些属性不可为空)。谢谢你的帮助。

1 个答案:

答案 0 :(得分:6)

  

我所做的就是制作一些不可空的属性

好吧,通常将非可空(必需)表列转换为可空(可选)没有问题,但不是相反,所以最好提前仔细考虑。

这里的“小”问题是大多数属性都是外键,这使转换更加复杂。 EF Core自动生成的迁移尝试通过在更改列之前删除FK约束并在之后重新创建它来正确处理。不幸的是,FK约束通常具有关联索引(如果您发现为例如“FK_Task_AspNetUsers_UserId”创建的迁移),您应该看到它还创建了索引“IX_Task_UserId”,并且它们忘记了删除并重新创建索引,这导致你得到的例外(它来自数据库)。

因此,您需要手动修复生成的迁移(您还可以考虑将错误报告发布到EF Core存储库)。

为此,请在第一次AlterColumn电话前插入以下内容:

migrationBuilder.DropIndex(
    name: "IX_Task_UserId",
    table: "Task");

以及最后一次AlterColumn来电后的以下内容:

migrationBuilder.CreateIndex(
    name: "IX_Task_UserId",
    table: "Task",
    column: "UserId");

问题应该解决。

请注意,您可能需要对迁移中包含的其他表执行类似操作,即类似这样的操作(确保从相应的初始迁移中验证名称):

migrationBuilder.DropIndex(
    name: "IX_TaskList_UserId",
    table: "TaskList");

migrationBuilder.DropIndex(
    name: "IX_Template_UserId",
    table: "Template");

然后:

migrationBuilder.CreateIndex(
    name: "IX_TaskList_UserId",
    table: "TaskList",
    column: "UserId");

migrationBuilder.CreateIndex(
    name: "IX_Template_UserId",
    table: "Template",
    column: "UserId");