执行迁移 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的主要内容,如果未能解决你的问题,请参考以下文章
.NET Core 2.0 和 EF 下是不是需要使用 IdentityDbContext 进行 JWT 身份验证?
如何在 ASP.NET Core 2.0 中设置多个身份验证方案?