EF Core中显式ID插入种子数据报错的解决方案咨询
解决EF Core种子数据显式指定ID的问题
我之前处理过类似的场景,结合你的情况,给你几个针对性的解决方案:
1. 修正IDENTITY_INSERT的执行逻辑与配置
你之前的代码顺序有问题,而且要确保EF Core和数据库的列配置匹配:
首先确认ID列的标识配置
在OnModelCreating里明确把Id设为标识列(如果还没做的话),同时指定正确的schema:
modelBuilder.Entity<Member>(entity => { entity.HasKey(e => e.Id); // 确保Id是数据库自增标识列 entity.Property(e => e.Id).ValueGeneratedOnAdd(); // 绑定到指定的schema和表名 entity.ToTable("Members", "blipp"); });
调整IDENTITY_INSERT的执行顺序与事务包裹
EF Core的SaveChanges会提前生成SQL语句,所以要先开启IDENTITY_INSERT,再添加实体并保存,最后关闭。同时用事务包裹避免状态异常:
using var transaction = Context.Database.BeginTransaction(); try { // 先开启IDENTITY_INSERT Context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT blipp.Members ON"); var member = new Member { Id = MemberId1, UserName = "member1" }; Context.Add(member); Context.SaveChanges(); // 关闭IDENTITY_INSERT Context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT blipp.Members OFF"); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); // 这里可以添加日志或自定义异常处理逻辑 throw; }
注意:EF Core 3.0+推荐用ExecuteSqlRaw代替已过时的ExecuteSqlCommand。
2. 直接使用SQL语句插入(绕开EF实体跟踪)
如果上述方法还是受限于拥有实体的限制,你可以直接执行原生SQL插入,这样更灵活,完全避开EF的实体规则:
using var transaction = Context.Database.BeginTransaction(); try { Context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT blipp.Members ON"); // 直接执行插入SQL,参数化避免注入 Context.Database.ExecuteSqlRaw( "INSERT INTO blipp.Members (Id, UserName) VALUES (@Id, @UserName)", new SqlParameter("@Id", MemberId1), new SqlParameter("@UserName", "member1") ); Context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT blipp.Members OFF"); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); throw; }
3. 排查schema与数据库实际表的匹配问题
你之前报错“Table 'blipp.Members' does not have the identity property”,大概率是schema名称错误。去数据库里确认Members表的schema是不是blipp——如果实际是dbo或者其他schema,把SQL里的blipp换成正确的名称即可解决这个报错。
内容的提问来源于stack exchange,提问作者Konrad Viltersten
相关产品推荐
相关产品推荐

