Toggle navigation
沐见南的博客
主页
博客
个人作品
关于博主
注册
登录
Toggle cookie consent banner
本站点使用Cookie记录您的信息
详情
接受
EF Core 变更外键关联字段的名称或数据类型
沐见南
主外键关联着的字段,无法变更其中任意一个的名称、类型、大小。要想变更,可以使用Sql解除这些状态。 而EF为我生成的代码,并没有先解除字段关联再更改字段类型。 三种方案,一是迁移前备份库结构,解除外键关联,顺利迁移之后再加回来;二是迁移前备份库(表),删除所有迁移记录,删除相关表格,生成新的迁移语句(也就是创建语句)之后直接重新建库(表),最后按先主表后关联表的顺序导入原数据;三是在EF生成的代码的基础上进行修改,在必要的位置加上解除关联的语句,操作完成后的位置加上还原关联的语句。 下面是我使用方案三的案例: 1. EF Core为我生成的代码 using Microsoft.EntityFrameworkCore.Migrations; namespace MuJianNanBlog.Migrations { public partial class ChangeDataType : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserName", table: "AspNetUsers", maxLength: 256, nullable: true, oldClrType: typeof(string), oldMaxLength: 128, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetUsers", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "ProviderKey", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserClaims", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetRoles", maxLength: 256, nullable: true, oldClrType: typeof(string), oldMaxLength: 128, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetRoles", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetRoleClaims", nullable: false, oldClrType: typeof(string)); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetUserTokens", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserTokens", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserName", table: "AspNetUsers", maxLength: 128, nullable: true, oldClrType: typeof(string), oldMaxLength: 256, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetUsers", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "ProviderKey", table: "AspNetUserLogins", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserLogins", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserClaims", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetRoles", maxLength: 128, nullable: true, oldClrType: typeof(string), oldMaxLength: 256, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetRoles", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetRoleClaims", nullable: false, oldClrType: typeof(string)); } } } 2. 我修改后的代码 注意两处注释 using Microsoft.EntityFrameworkCore.Migrations; namespace MuJianNanBlog.Migrations { public partial class ChangeDataType : Migration { protected override void Up(MigrationBuilder migrationBuilder) { //Drop FKs migrationBuilder.DropForeignKey(name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", table: "AspNetRoleClaims"); migrationBuilder.DropForeignKey(name: "FK_AspNetUserClaims_AspNetUsers_UserId", table: "AspNetUserClaims"); migrationBuilder.DropForeignKey(name: "FK_AspNetUserLogins_AspNetUsers_UserId", table: "AspNetUserLogins"); migrationBuilder.DropForeignKey(name: "FK_AspNetUserRoles_AspNetRoles_RoleId", table: "AspNetUserRoles"); migrationBuilder.DropForeignKey(name: "FK_AspNetUserRoles_AspNetUsers_UserId", table: "AspNetUserRoles"); migrationBuilder.DropForeignKey(name: "FK_AspNetUserTokens_AspNetUsers_UserId", table: "AspNetUserTokens"); migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserName", table: "AspNetUsers", maxLength: 256, nullable: true, oldClrType: typeof(string), oldMaxLength: 128, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetUsers", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "ProviderKey", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserClaims", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetRoles", maxLength: 256, nullable: true, oldClrType: typeof(string), oldMaxLength: 128, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetRoles", nullable: false, oldClrType: typeof(string), oldMaxLength: 128); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetRoleClaims", nullable: false, oldClrType: typeof(string)); //Restore FKs migrationBuilder.AddForeignKey( name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", table: "AspNetRoleClaims", column: "RoleId", principalTable: "AspNetRoles", principalColumn: "Id", onDelete: ReferentialAction.Cascade); migrationBuilder.AddForeignKey( name: "FK_AspNetUserClaims_AspNetUsers_UserId", table: "AspNetUserClaims", 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_AspNetUserRoles_AspNetRoles_RoleId", table: "AspNetUserRoles", column: "RoleId", principalTable: "AspNetRoles", 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_AspNetUserTokens_AspNetUsers_UserId", table: "AspNetUserTokens", column: "UserId", principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetUserTokens", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserTokens", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserTokens", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserName", table: "AspNetUsers", maxLength: 128, nullable: true, oldClrType: typeof(string), oldMaxLength: 256, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetUsers", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserRoles", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserLogins", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "ProviderKey", table: "AspNetUserLogins", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "LoginProvider", table: "AspNetUserLogins", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "UserId", table: "AspNetUserClaims", nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "Name", table: "AspNetRoles", maxLength: 128, nullable: true, oldClrType: typeof(string), oldMaxLength: 256, oldNullable: true); migrationBuilder.AlterColumn<string>( name: "Id", table: "AspNetRoles", maxLength: 128, nullable: false, oldClrType: typeof(string)); migrationBuilder.AlterColumn<string>( name: "RoleId", table: "AspNetRoleClaims", nullable: false, oldClrType: typeof(string)); } } } 可以看到,我只是简单地在Up方法的首尾加了外键的移除和恢复代码。 如果需要还原迁移,可以在Down方法里也加上一些代码(不过一般没必要,直接进数据库还原库、Git还原代码会更方便)。 **参考:** 1. [自定义迁移操作](https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/operations)
留言板: