执行迁移 EF core 2.0 时出错,将身份 ID 从字符串更改为 int

Posted

技术标签:

【中文标题】执行迁移 EF core 2.0 时出错,将身份 ID 从字符串更改为 int【英文标题】:Error while doing Migrations EF core 2.0, changing Identity id from string to int 【发布时间】:2018-03-23 16:22:58 【问题描述】:

场景:

我从同事那里收到了 ASP.NET CORE 中自动生成的项目。帐户/管理服务有自动生成的代码。此代码包括 ApplicationUser 类、DBContext 和迁移文件夹,其中包含 00000000000000_CreateIdentitySchema.cs 和 20180323155805_Snapshot.cs。我一直在尝试将我的 User 类更改为具有整数 ID。为此,我向 IdentityUser 添加了泛型:

public class ApplicationUser : IdentityUser**<int>**


我还必须创建 ApplicationRole 类,因为之前它已在迁移文件中创建。

public class ApplicationRole : IdentityRole<int>


我也改变了我的上下文:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, 
    **ApplicationRole, int**>

在迁移文件中,创建了登录方案。添加更改后,我添加了新的迁移。在添加迁移期间,我收到此错误:

要更改列的 IDENTITY 属性,需要删除并重新创建该列。

【问题讨论】:

【参考方案1】:

您需要更新生成的迁移以分步进行。将AlterColumn 调用替换为以下操作:

    使用临时名称添加新列 删除原始列 使用原始列名重命名新列

您可能还必须重建(删除并重新创建)引用该列的所有约束。

这不是微不足道的,这就是 EF 目前不处理它的原因。功能请求#329 是关于更新 EF 以自动处理此问题。

【讨论】:

【参考方案2】:

我创建了一个迁移脚本来完成这项工作。首先,我生成了脚本并进行了一些更改。

            migrationBuilder.DropForeignKey(name: "FK_AspNetUserTokens_AspNetUsers_UserId", table: "AspNetUserTokens");
            migrationBuilder.DropForeignKey(name: "FK_AspNetUserRoles_AspNetUsers_UserId", table: "AspNetUserRoles");
            migrationBuilder.DropForeignKey(name: "FK_AspNetUserLogins_AspNetUsers_UserId", table: "AspNetUserLogins");
            migrationBuilder.DropForeignKey(name: "FK_AspNetUserClaims_AspNetUsers_UserId", table: "AspNetUserClaims");
            migrationBuilder.DropPrimaryKey(name: "PK_AspNetUsers", table: "AspNetUsers");

            migrationBuilder.DropForeignKey(name: "FK_AspNetUserRoles_AspNetRoles_RoleId", table: "AspNetUserRoles");
            migrationBuilder.DropForeignKey(name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", table: "AspNetRoleClaims");
            migrationBuilder.DropPrimaryKey(name: "PK_AspNetRoles", table: "AspNetRoles");

            migrationBuilder.DropPrimaryKey(name: "PK_AspNetUserTokens", table: "AspNetUserTokens");

            migrationBuilder.DropPrimaryKey(name: "PK_AspNetUserRoles", table: "AspNetUserRoles");

            migrationBuilder.AddColumn<int>(name: "Idtmp", table: "AspNetUsers").Annotation("SqlServer:Identity", "1, 1"); ;
            migrationBuilder.DropColumn(name: "Id", table: "AspNetUsers");
            migrationBuilder.RenameColumn(name: "IdTmp", table: "AspNetUsers", "Id");

            migrationBuilder.AddColumn<int>(name: "Idtmp", table: "AspNetRoles").Annotation("SqlServer:Identity", "1, 1"); ;
            migrationBuilder.DropColumn(name: "Id", table: "AspNetRoles");
            migrationBuilder.RenameColumn(name: "IdTmp", table: "AspNetRoles", "Id");

            migrationBuilder.AlterColumn<int>(name: "UserId", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string), oldType: "nvarchar(450)");
            migrationBuilder.AlterColumn<int>(name: "RoleId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string), oldType: "nvarchar(450)");
            migrationBuilder.AlterColumn<int>(name: "UserId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string), oldType: "nvarchar(450)");
            migrationBuilder.AlterColumn<int>(name: "UserId", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string), oldType: "nvarchar(450)");
            migrationBuilder.AlterColumn<int>(name: "UserId", table: "AspNetUserClaims", nullable: false, oldClrType: typeof(string), oldType: "nvarchar(450)");
            migrationBuilder.AlterColumn<int>(name: "RoleId", table: "AspNetRoleClaims", nullable: false, oldClrType: typeof(string), oldType: "nvarchar(450)");

            migrationBuilder.AddPrimaryKey(name: "PK_AspNetUserRoles", table: "AspNetUserRoles", columns:new[]  "UserId", "RoleId");

            migrationBuilder.AddPrimaryKey(name: "PK_AspNetUserTokens", table: "AspNetUserTokens", columns:new[]  "UserId", "LoginProvider", "Name" );

            migrationBuilder.AddPrimaryKey(name: "PK_AspNetRoles", table: "AspNetRoles", column: "Id");
            migrationBuilder.AddForeignKey(name: "FK_AspNetUserRoles_AspNetRoles_RoleId", table: "AspNetUserRoles", column: "RoleId", principalTable: "AspNetRoles", principalColumn: "Id", onDelete: ReferentialAction.Cascade);
            migrationBuilder.AddForeignKey(name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", table: "AspNetRoleClaims", column: "RoleId", principalTable: "AspNetRoles", principalColumn: "Id", onDelete: ReferentialAction.Cascade);


            migrationBuilder.AddPrimaryKey(name: "PK_AspNetUsers", table: "AspNetUsers", column: "Id");
            migrationBuilder.AddForeignKey(name: "FK_AspNetUserTokens_AspNetUsers_UserId", table: "AspNetUserTokens", column: "UserId", principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade);
            migrationBuilder.AddForeignKey(name: "FK_AspNetUserRoles_AspNetUsers_UserId", table: "AspNetUserRoles", column: "UserId", principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade);
            migrationBuilder.AddForeignKey(name: "FK_AspNetUserLogins_AspNetUsers_UserId", table: "AspNetUserLogins", column: "UserId", principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade);
            migrationBuilder.AddForeignKey(name: "FK_AspNetUserClaims_AspNetUsers_UserId", table: "AspNetUserClaims", column: "UserId", principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade);

【讨论】:

这非常有效,尽管我必须将 dropcolumn 移到用户和角色身份的 addcolumn 上方,因为您无法向这些表添加第二个身份列。【参考方案3】:

使用 CLI 命令解决

dotnet ef migrations add CreateIdentitySchema
dotnet ef database update

【讨论】:

以上是关于执行迁移 EF core 2.0 时出错,将身份 ID 从字符串更改为 int的主要内容,如果未能解决你的问题,请参考以下文章

从 EF Core 5 迁移到 EF Core 6 时出错

.NET Core 2.0 和 EF 下是不是需要使用 IdentityDbContext 进行 JWT 身份验证?

如何在 ASP.NET Core 2.0 中设置多个身份验证方案?

将 jsf 1.2 迁移到 2.0 时出错

从 ASP.NET Core 1.1 MVC 迁移到 2.0 后,自定义 cookie 身份验证不起作用

EF Core 迁移:在存在时删除唯一约束