c# ef报错_关于c#:在EF 6中更新现有数据会引发异常-“…同一类型的实体已经具有相同的主键值。”...

我正在尝试使用Entity Framework 6,代码优先,没有流畅的映射或类似Automapper的工具来更新记录。

实体(Employee)具有与其关联的其他复合属性,例如Addreess(collection),Department

它也从称为User的基础继承

保存方法如下,其中_dbContext是DbConext的实现

public bool UpdateEmployee(Employee employee)

{

var entity = _dbContext.Employees.Where(c => c.Id == employee.Id).AsQueryable().FirstOrDefault();

if (entity == null)

{

_dbContext.Employees.Add(employee);

}

else

{

_dbContext.Entry(employee).State = EntityState.Modified; //

_dbContext.Employees.Attach(employee);

}

return _dbContext.SaveChanges() > 0;

}

我不断收到错误:

Attaching an entity of type failed because another entity of the same

type already has the same primary key value. This can happen when

using the 'Attach' method or setting the state of an entity to

'Unchanged' or 'Modified' if any entities in the graph have

conflicting key values. This may be because some entities are new and

have not yet received database-generated key values. In this case use

the 'Add' method or the 'Added' entity state to track the graph and

then set the state of non-new entities to 'Unchanged' or 'Modified' as

appropriate.

我尝试了以下方法:

设置为EntityState.Modified之前附加

在查询对象是否存在时添加AsNoTracking()(无异常但未更新DB)-https://stackoverflow.com/a/23228001/919426

使用基本实体_dbContext.Users而不是Employee实体进行保存-https://stackoverflow.com/a/25575634/919426

现在没有一个对我有用。

对于某些无法在我的情况下使用的解决方案,我可能会犯什么错误?

使用var entity = _dbContext.Employees.FirstOrDefault(c => c.Id == employee.Id);

dbContext的寿命是多少? 我敢打赌您不会经常创建新的上下文。

请查看我在ASP.NET MVC上的答案-附加类型为MODELNAME的实体失败,因为相同类型的另一个实体已经具有相同的主键值。

假设您没有要更新的导航属性,EF已经提供了一种无需使用Automapper即可映射属性的方法:

public bool UpdateEmployee(Employee employee)

{

var entity = _dbContext.Employees.Where(c => c.Id == employee.Id).AsQueryable().FirstOrDefault();

if (entity == null)

{

_dbContext.Employees.Add(employee);

}

else

{

_dbContext.Entry(entity).CurrentValues.SetValues(employee);

}

return _dbContext.SaveChanges() > 0;

}

这通常会生成更好的SQL语句,因为它只会更新已更改的属性。

如果仍然要使用原始方法,则可以使用AsNoTracking从上下文中摆脱entity(不确定为什么在您的情况下它没有更新,它应该没有效果,所以问题可能是或修改查询,以防止它首先实现实体,例如使用bool exists = dbContext.Employees.Any(c => c.Id == employee.Id)之类的东西。

我确实提到我没有使用Automapper。我确实具有navigatin属性(在复合类ike Address和Department中。您是说我当时需要Automapper吗?。您的代码未导致异常,但数据库未更新

您要修改对象的属性还是其他?如果要修改整个对象图,则必须遍历该图并将所有项目标记为已修改。

我有一个Employee记录,我想使用Entiy Framework(它的新功能)进行更新。据我重新设置,我使用的方法应该可以工作。我不知道过程中涉及对象图吗?请根据您的最新评论来解释替代方案。我有一个具有导航属性的对象Employee。我只想更新那条Employee记录...如何完成?可能是什么原因导致我使用的方法出错?

如果您仅更新雇员对象,则此方法应该有效。看看在那种情况下将什么SQL语句传递给数据库。您的原始方法无效,因为您不能在同一DbContext中两次拥有相同的实体(在这种情况下,原始对象和您要更新的对象)

好。将不得不检查代码并配置数据库,然后在重新启动数据库服务器和客户端PC之后(以防万一),将测试所有建议的方法

这对我自己有用

var aExists = _db.Model.Find(newOrOldOne.id);

if(aExists==null)

{

_db.Model.Add(newOrOldOne);

}

else

{

_db.Entry(aExists).State = EntityState.Detached;

_db.Entry(newOrOldOne).State = EntityState.Modified;

}

使用存储库和工作单元模式时,我遇到了同样的事情(如带有ef5的mvc4教程中所述)。

GenericRepository包含一个Update(TEntity)方法,该方法尝试附加,然后设置Entry.State = Modified。如果您要坚持使用uow / repo模式,则上面被投票否定的"答案"不能解决此问题。

我确实尝试在附加之前使用分离过程,但是由于与最初问题中所述相同的原因,它仍然失败。

事实证明,这样做的原因是我在检查是否存在记录,然后在调用update()之前使用automapper从dto中生成了一个实体对象。

通过检查该记录是否存在,我将实体对象放到了作用域中,并且无法分离它(这也是最初的提问者无法分离的原因)... Tt跟踪了记录,但没有我将dto自动映射到一个实体,然后尝试更新后,不允许进行任何更改。

这是通用仓库的更新实现:

public virtual void Update(TEntity entityToUpdate)

{

dbSet.Attach(entityToUpdate);

context.Entry(entityToUpdate).State = EntityState.Modified;

}

这是我的PUT方法(我在Angular中使用WebApi)

[HttpPut]

public IHttpActionResult Put(int id, Product product)

{

IHttpActionResult ret;

try

{

// remove pre-check because it locks the record

// var e = unitOfWork.ProductRepository.GetByID(id);

//  if (e != null) {

var toSave = _mapper.Map(product);

unitOfWork.ProductRepository.Update(toSave);

unitOfWork.Save();

var p = _mapper.Map(toSave);

ret = Ok(p);

// }

// else

//    ret = NotFound();

}

catch (DbEntityValidationException ex)

{

ret = BadRequest(ValidationErrorsToMessages(ex));

}

catch (Exception ex)

{

ret = InternalServerError(ex);

}

return ret;

}

如您所见,我已将检查删除,以查看记录是否存在。我想如果我尝试更新不再存在的记录,因为我不再有NotFound()返回机会,我将看到它的工作原理。

因此,要回答最初的问题,我会说在尝试之前不要寻找entity == null,或者想出另一种方法。也许就我而言,发现对象后我可以处置UnitOfWork,然后进行更新。

您需要分离以避免在调用SaveChanges时出现重复的主键异常

db.Entry(entity).State = EntityState.Detached;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值