EF Core 2.1 Code First迁移报错:需删改列修改IDENTITY属性
解决EF Core 2.1 Code First中IDENTITY属性变更的报错问题
嘿,我之前也踩过这个坑,给你唠唠怎么解决:
你遇到的这个报错「To change the IDENTITY property of a column, the column needs to be dropped and recreated.」本质是SQL Server的限制——它不允许直接修改一个列的IDENTITY(自增)属性,必须删了重造。结合你的实体代码来看,大概率是EF Core自动推断列属性时出了岔子,比如误把外键PartOfSpeechId标记成了自增列,或者主键的自增配置在迁移过程中发生了冲突。
下面分几种场景给你解决方案:
场景1:数据库还在开发初期,数据可以丢弃
这是最省心的办法:
- 直接删掉本地的测试数据库
- 把项目里
Migrations文件夹下的迁移文件全删了(DbContextModelSnapshot.cs可以留着,或者一起删了重新生成) - 重新执行
add-migration InitialCreate生成干净的初始迁移 - 再跑
update-database,之后重新运行你的Seed代码就行
场景2:需要保留现有数据,手动修改迁移文件
如果你不想丢失现有数据,就得手动调整EF生成的迁移脚本:
- 先执行
add-migration FixIdentityIssue生成新的迁移文件 - 打开这个迁移文件,找到里面类似
migrationBuilder.AlterColumn<int>(...)的语句——这就是EF尝试修改IDENTITY属性的代码,直接删掉它 - 替换成「先删外键→删列→重建列→重新加外键」的逻辑,针对你的
PartOfSpeechId外键,代码大概是这样:// 先移除外键约束 migrationBuilder.DropForeignKey( name: "FK_Dictionaries_PartOfSpeeches_PartOfSpeechId", table: "Dictionaries"); // 删除原有的PartOfSpeechId列 migrationBuilder.DropColumn( name: "PartOfSpeechId", table: "Dictionaries"); // 重建列,注意这里不要加Identity()!外键不需要自增 migrationBuilder.AddColumn<int>( name: "PartOfSpeechId", table: "Dictionaries", nullable: false, defaultValue: 0); // 如果要保留原有数据,可先临时备份数据再恢复,开发阶段一般不用这么麻烦 // 重新添加外键约束 migrationBuilder.AddForeignKey( name: "FK_Dictionaries_PartOfSpeeches_PartOfSpeechId", table: "Dictionaries", column: "PartOfSpeechId", principalTable: "PartOfSpeeches", principalColumn: "Id", onDelete: ReferentialAction.Cascade); - 保存后执行
update-database就可以了
场景3:从根源避免问题——显式配置实体
其实最好的办法是不让EF瞎猜,用Fluent API显式配置你的实体关系,这样后续迁移就不会出意外。在你的DbContext里重写OnModelCreating方法:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置Dictionary实体:主键是Id(默认自增),外键是PartOfSpeechId关联PartOfSpeech modelBuilder.Entity<Dictionary>() .HasKey(d => d.Id); modelBuilder.Entity<Dictionary>() .HasOne(d => d.PartOfSpeech) .WithMany(p => p.Dictionary) .HasForeignKey(d => d.PartOfSpeechId); // 配置PartOfSpeech实体:主键是Id(默认自增) modelBuilder.Entity<PartOfSpeech>() .HasKey(p => p.Id); }
这样EF就明确知道PartOfSpeechId是外键,不会把它设成自增列,从根源避免这个报错。
最后提一句你的Seed代码:执行的时候要确保PartOfSpeech表已经有Id=6的记录哦,不然会触发外键约束错误,最好先SeedPartOfSpeech的数据,再SeedDictionary。
内容的提问来源于stack exchange,提问作者kenzolek
相关产品推荐
相关产品推荐

