为什么我不能修改我的模型:具有相同键的对象已存在异常

时间:2015-09-05 17:49:23

标签: c# .net entity-framework

我有一个模型,我们可以调用Person

// My table tb_person
public class Person
{
   public int Id {get;set;}
   public string Name {get; set;}
   public int Age {get; set;}
   public DateTime AddTime {get; set;}
   public DateTime UPdateTime {get;set;}
   public string Remark {get; set}
   public bool IsEnable {get;set;}
}

首先我得到了Mdoel

using (var ctx = new MyEntitys())
{
  ctx.Configuration.ProxyCreationEnabled = false;
  ctx.Configuration.LazyLoadingEnabled = false;

  Person firstModel = ctx.Persons.Where( x=> x.Id = 5).FirstOrDefault();
}

现在很长一段时间我需要修改模型,但我需要在数据库中获取旧模型并进行比较。

using (var ctx = new MyEntitys())
{
  ctx.Configuration.ProxyCreationEnabled = false;
  ctx.Configuration.LazyLoadingEnabled = false;

  Person CurrentModel = ctx.Persons.Where( x=> x.Id = 5).FirstOrDefault();
   // Just a example for judge or compare
   if (CurrentModel.IsEnable)
   {
       if (CurrentModel.UpdateTime != null)
      {
         firstModel.Update = time;
      }
   }
   else
    {
        firstModel.AddTime = new DateTime();
    }
     ctx.Entry(firstModel).State = System.Data.Entity.EntityState.Modified;
     ctx.SaveChanges();
}

然后它将抛出:

为什么我不使用CurrentModel进行更新?由于firstModel我更改了这么多属性,我不想复制所有属性。我只需要从数据库中获取一些信息,然后将其替换为Save。

我已经看到了这一点:An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

那样我不喜欢它。我感到困惑,而且很复杂。

我也尝试用另一种方法来修复它:

//只是在没有得到它的情况下判断它

if (ctx.Persons.Any( x=> x.Id = 5 && x.UpdateTime != null){
  // then do something change after judge
}

基本上现在我知道问题来源:实体框架在获取后缓存结果。这就是为什么在我得到一个新模型之后,它不允许我使用旧模型。

但我仍在寻找一种更好的高度表现方式(我只想减少与数据库的交易)来修复它。 你有什么想法吗?

1 个答案:

答案 0 :(得分:1)

当您使用Entry()获取对象的条目时,上下文检查上下文中是否存在该对象引用的条目然后返回它,如果该对象引用没有条目,则它添加一个该对象进入上下文。

当您创建var p1= new Person()var p2=new Person()时,p1和p2不一样,即使它们的所有属性相同,它们也有不同的引用。

在您的情况下,修改后的实体(第一个)和原始实体是不同的实例,因此上下文尝试首先创建一个条目,因为您已将原始版本加载到上下文中,将抛出Object with the same key already exists的异常。

要了解您可以做什么,请考虑以下情况:

情景1

在这种情况下,您从上下文中获取一个人并将其传递给客户端,然后客户端将修改后的版本发送给您以放入数据库,并且您还要检查某人的原始版本,然后更新数据库。 你应该这样做:

//get original version
original= context.Persons.Where( x=> x.Id = modified.Id ).FirstOrDefault();
//do comparison and what you want to do
//but only apply changes to modified version
if (original.Age > 20)
    modified.SomeProperty=SomeValue;

//save modified version
context.Entry(original).CurrentValues.SetValues(modified);
context.SaveChanges();

这种方式类似于以前版本ApplyCurrentValuesObjectContext的{​​{1}}方法

场景2

在这种情况下,您从上下文中获取一个人并将其传递给客户端,然后客户端将修改后的版本发送给您,而您(无需检查原始版本)将其放入数据库中。

你应该这样做:

Entity Framework

并且没有必要找到原件。

更多信息: