首页 > 解决方案 > .NET Core 2.2 Migration Builder 无法删除索引

问题描述

我正在尝试从 IdentityUserRole 表中名为 UserRole 的列中删除索引/外键。

UserRole 有 2 列。用户 ID 和角色 ID。两者都是主键。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    
    var rolesTable = modelBuilder.Entity<Role>().ToTable("Role");
    var userRolesTable = modelBuilder.Entity<UserRole>().ToTable("UserRole");
    var userClaimsTable = modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("UserClaim");
    var usersTable = modelBuilder.Entity<User>().ToTable("User");

    modelBuilder.Entity<Role>(builder =>
    {
        builder.Metadata.RemoveIndex(new[] { builder.Property(u => u.NormalizedName).Metadata });
    });
    modelBuilder.Entity<UserRole>(builder =>
    {
        builder.Metadata.RemoveIndex(new[] { builder.Property(u => u.RoleId).Metadata});
    });
    

}

但是,每当我运行迁移并更新数据库时,仍会出现此索引:

IX_UserRole_RoleId 列 RoleId

编辑:这是生成的迁移

migrationBuilder.CreateTable(
    name: "UserRole",
    columns: table => new
    {
        UserId = table.Column<string>(nullable: false),
        RoleId = table.Column<string>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_UserRole", x => new { x.UserId, x.RoleId });
        table.ForeignKey(
            name: "FK_UserRole_Role_RoleId",
            column: x => x.RoleId,
            principalTable: "Role",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_UserRole_User_UserId",
            column: x => x.UserId,
            principalTable: "User",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    });

migrationBuilder.CreateIndex(
    name: "IX_UserRole_RoleId",
    table: "UserRole",
    column: "RoleId");

标签: c#entity-frameworkasp.net-core.net-coreentity-framework-core

解决方案


按照惯例,EF Core 为每个 FK 列添加索引,该列不是另一个索引的前导部分。即使您没有使用这些索引的查询,但通常它们对于强制执行 FK 约束以及实现级联删除很有用,因此事实上它们是关系数据库设计中的标准(类似于用于强制唯一索引的唯一索引/ PK约束等)但这不是这里的问题。

RemoveIndex您可能认为它是缺陷,但即使您使用显式元数据 API ,也无法删除约定引入的索引。它会删除它们,但随后它们会自动添加回来。

这是因为 EF Core 约定不是静态应用的。它们由监听不同模型元数据更改的类实现,这些更改触发“重新应用”约定。

很快,您将无法使用元数据/流式 API 删除此类索引。如果您真的想删除它们(我不推荐),您应该手动编辑生成的迁移并从UpDown方法中删除相应的创建/删除命令。


推荐阅读