【问题标题】:Unable to save because of 'another entity of the same type already has the same primary key value'无法保存,因为“同一类型的另一个实体已经具有相同的主键值”
【发布时间】:2015-12-15 14:21:19
【问题描述】:

我有这个控制器动作:

[HttpGet]
[Route("api/person/test/{id}")]
public IHttpActionResult Test(Guid id)
{
    var person = this.PersonManager.Get(id);

    person.Lastname = "Jameson";

    this.PersonManager.Save(person);

    return Ok(true);
}

在这个保存方法的深处调用:

protected void Add<T>(T source, MyEntities context, bool isNew) where T : class
{
    if (isNew)
    {
        context.Set<T>().Add(source);
    }
    else
    {
        var entry = context.Entry(source);
        if (entry.State == EntityState.Detached)
        {
            context.Set<T>().Attach(source);

            entry.State = EntityState.Modified;
        }
    }
}

执行此操作时出现此错误:

附加类型为“Model.Person”的实体失败,因为另一个 相同类型的实体已经具有相同的主键值。这个 使用“附加”方法或设置状态时可能发生 如果图中的任何实体具有,则实体为“未更改”或“已修改” 键值冲突。这可能是因为一些实体是新的并且 尚未收到数据库生成的键值。在这种情况下使用 'Add' 方法或 'Added' 实体状态来跟踪图形和 然后将非新实体的状态设置为“未更改”或“已修改”为 合适。

它出现在context.Set&lt;T&gt;().Attach(source) 行。

PS:这是question 的后续/衍生。

【问题讨论】:

  • 如果您使用 Get 加载它,为什么在这种情况下您的实体会分离?看起来它已加载并保存在 DbContext 中,因此当您再次附加它时,它与自身的原始副本冲突。您还处理 Get 和 Save 操作之间的上下文吗?
  • @raderick:好问题。这是一个后续问题,是关于意外的 Dispose。这可能是导致此问题的原因。
  • 您绝对应该跟踪您的人员实体从加载到再次保存的实体状态,看起来在某些时候它已分离但也保持在相同的上下文中,所以当您再次附加它时会发生此问题。
  • 您能否检查context.person.Local 以查看是否有一个人对象与更新的人对象具有相同的主对象?

标签: c# .net asp.net-mvc entity-framework


【解决方案1】:

试试这个

if (!context.Set<T>().Local.Contains(source))
 {
    context.Set<T>().Attach(source);
 }

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

【讨论】:

  • 谢谢,但这基本上是做同样事情的不同方式。所以,同样的错误。
  • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
  • 这段代码不就是少了一个else来处理已经附加了对象的情况,然后你使用Add的方法吗?无论如何,对于任何寻求解决方案的人,看看这个答案是否有帮助:stackoverflow.com/questions/11705569/…
猜你喜欢
  • 2017-08-10
  • 2015-01-08
  • 2014-07-18
  • 2018-10-14
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多