Linq to SQL报错Cannot attach an entity that already exists的解决咨询
问题原因
你遇到的Cannot attach an entity that already exists错误,核心原因是:你从数据库查询出来的adminConfig已经被当前的DataContext跟踪了,此时再调用DbSet.Attach(entity)尝试附加实体,上下文会检测到已有同一主键的实体存在,因此抛出冲突错误。
看你的代码:GetAdminConfig()通过GetRepository().Get(...)查询实体,这个查询操作会让DataContext自动跟踪返回的AdminConfig实例,后续你修改它的属性后,直接提交更改即可,不需要再手动执行Attach。
解决方案
方案1:简化代码,移除不必要的Attach操作
既然查询出来的实体已经被跟踪,直接修改属性后提交更改就行,不需要调用Update方法里的Attach。
修改ResetAdminConfig和Update方法:
public void ResetAdminConfig(AdminConfig _adminConfig) { AdminConfig adminConfig = GetAdminConfig(_adminConfig.Id); // 修正原代码中GetAdminConfig的参数传递问题 if (adminConfig == null) return; adminConfig.ConfigSetting = false; adminConfig.Modified = DateTime.Now; // 直接提交上下文更改,无需调用Update方法 UnitOfWork.Context.SubmitChanges(); } // 若需保留Update方法,修改为仅处理未被跟踪的实体 public void Update(TEntity entity) { // 检查实体是否已被上下文跟踪 var original = _context.GetOriginalEntityState(entity); if (original == null) { // 仅当实体未被跟踪时执行Attach DbSet.Attach(entity); } _context.Refresh(RefreshMode.KeepCurrentValues, entity); }
方案2:处理离线实体的更新场景
如果你的场景需要处理离线实体(比如前端传入的、未被当前上下文跟踪的实体),可以先查询数据库中的原有实体,再将离线实体的属性赋值给它,最后提交更改,完全避开Attach操作:
public void ResetAdminConfig(AdminConfig _adminConfig) { AdminConfig adminConfig = GetAdminConfig(_adminConfig.Id); if (adminConfig == null) return; // 将传入实体的属性同步到跟踪中的实体 adminConfig.ConfigSetting = false; adminConfig.Modified = DateTime.Now; UnitOfWork.Context.SubmitChanges(); }
关键要点
- Linq to Sql中,通过
Table<T>.Get()或查询方法返回的实体,默认会被DataContext跟踪,此时不需要手动调用Attach。 - 只有当实体处于离线状态(比如新创建的、外部传入的、未被当前上下文跟踪的)时,才需要执行
Attach。 - 可以通过
_context.GetOriginalEntityState(entity)判断实体是否已被跟踪,避免重复Attach引发的冲突。
内容的提问来源于stack exchange,提问作者Jefferson
相关产品推荐
相关产品推荐

