开启IDENTITY_INSERT后仍报错,修改非标识字段触发问题求助
解决IDENTITY_INSERT开启后仍报错的问题
你的问题其实出在删除实体后重新添加时,EF仍然会尝试插入原有标识列的值,哪怕你只修改了非标识字段OrderValue。让我拆解下原因和解决方案:
问题根源
当你用db.games.Remove(gg)删除实体后,这个实体对象的id属性依然保留着原来的数值。当你调用db.games.Add(gg)时,EF会把这个对象当作全新的实体,尝试插入所有字段(包括id)。而你的game表中id是标识列,默认由数据库自动生成,所以数据库会拒绝手动插入id值——哪怕你开启了IDENTITY_INSERT,也可能因为上下文跟踪的状态不对导致报错。
而且更关键的是:你的需求只是修改OrderValue,完全没必要走“删除再添加”的流程,这是绕远路还触发了不必要的问题。
最优解决方案:直接修改字段保存
既然你的目标只是更新OrderValue,直接找到实体修改后保存即可,这是EF的常规用法:
public ActionResult Position(int ID) { var gg = db.games.Find(ID); gg.OrderValue = 42; // 直接修改目标字段 db.SaveChanges(); // 保存修改,EF会自动生成UPDATE语句 return RedirectToAction("Admin"); }
如果必须删除再添加(业务需求)
如果因为某些业务逻辑,你一定要删除实体后重新添加,那需要处理标识列的问题:
方案1:重置标识列值,让数据库重新生成
把实体的id设为默认值(SQL Server中int类型标识列设为0,数据库会自动生成新的标识值):
public ActionResult Position(int ID) { var gg = db.games.Find(ID); db.games.Remove(gg); db.SaveChanges(); // 先提交删除操作 gg.id = 0; // 重置标识列,让DB生成新值 gg.OrderValue = 42; db.games.Add(gg); db.SaveChanges(); return RedirectToAction("Admin"); }
方案2:保留原有ID,正确开启IDENTITY_INSERT
如果你需要保留原来的id值,那必须确保IDENTITY_INSERT的开启和关闭包裹住整个插入操作,并且EF明确知道要插入标识列的值:
public ActionResult Position(int ID) { var gg = db.games.Find(ID); db.games.Remove(gg); db.SaveChanges(); // 先完成删除 gg.OrderValue = 42; // 开启IDENTITY_INSERT db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT game ON"); db.games.Add(gg); db.SaveChanges(); // 操作完成后务必关闭,避免影响后续操作 db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT game OFF"); return RedirectToAction("Admin"); }
注意:IDENTITY_INSERT一次只能对一个表开启,操作完成后一定要关闭,否则其他针对该表的插入操作可能会报错。
内容的提问来源于stack exchange,提问作者Giga Sparselashvili
相关产品推荐
相关产品推荐

