无法在Entity Framework 6

时间:2015-07-25 15:24:56

标签: c# entity-framework

我有一个班级Customer。我正在尝试克隆一个Customer对象并对其进行修改,然后我希望这些修改能够反映在上下文中(数据库也是如此)。我正在使用以下代码来做到这一点。

    Customer old = context.Customers.Where(c=>c.CustomerID ==1 ).SingleOrDefault();
    Customer m = CustomExtensions.ShallowCopyEntity<Customer>(old);
    m.Name = "Modified";
    m.MobileNo = "9999999999";

    context.Customers.Attach(m);

但它抛出异常

  

附加“DataBindingSample.Customer”类型的实体   失败,因为同一类型的另一个实体已经相同   主键值。使用“附加”方法或时,可能会发生这种情况   将实体的状态设置为“未更改”或“已修改”(如果有)   图中的实体具有冲突的键值。这可能是因为   某些实体是新的,尚未收到数据库生成的密钥   值。在这种情况下,使用“添加”方法或“已添加”实体状态   跟踪图形,然后将非新实体的状态设置为   “视情况而定”或“修改”。

我尝试将EntityState更改为Modified但不起作用。

谁能告诉我如何实现这个目标?

我的主要目标是

  1. 我想克隆(我将在必要时使用深度克隆)现有实体
  2. 想要修改克隆的实体(以及引用的实体 - 在这种情况下我将使用深度克隆)
  3. 最后我想保存对数据库的更改
  4. 修改

    正如this注释中指出的那样,我试图附加在上下文中存在的对象。所以我可以先将它拆开然后再按照下图所示再贴上,如果附加是强制性的。

            Customer old = context.Customers.Where(c=>c.CustomerID ==1 ).SingleOrDefault();
            Customer m = CustomExtensions.ShallowCopyEntity<Customer>(old);
            m.Name = "Modified789789";
            m.MobileNo = "9999999999";
            ((IObjectContextAdapter)context).ObjectContext.Detach(old);
            context.Customers.Attach(m);
            context.Entry(m).State = EntityState.Modified;
            context.SaveChanges();
    

    否则我可以按照this回答中提到的2个选项进行操作。

1 个答案:

答案 0 :(得分:2)

我可以想到两个选项:

  1. 将更新后的值复制回加载到DbContext中的原始实体,然后保存更改。
  2. 更新了原始实体的值,然后在用户取消更新时将其丢弃。
  3. 选项1

    只需将更新后的值复制回最初加载的实体即可。 Automapper是你这样的任务的朋友。稍后可以扩展此方法以允许用户更改实体的模型而不是数据层对象本身(例如,公开用户可以编辑的有限数量的字段)。

    var entity = context.Customers.SingleOrDefault(c => c.CustomerID == 1);
    var updatedEntity = CustomExtensions.ShallowCopyEntity<Customer>(old);
    
    updatedEntity.Name = "Modified";
    updatedEntity.MobileNo = "9999999999";
    
    entity.Name = updatedEntity.Name;
    entity.MobileNo = updatedEntity.MobileNo;
    
    context.SaveChanges();
    

    如果添加Automapper nuget,那么映射(复制)将变得更加容易:

    Mapper.CreateMap<Customer, Customer>();
    Mapper.Map(updatedEntity, entity);
    

    您的代码将如下所示:

    // Configuring mapping. Needs to be done only once.
    Mapper.CreateMap<Customer, Customer>();
    
    var entity = context.Customers.SingleOrDefault(c => c.CustomerID == 1);
    
    // Check if entity is null
    
    var updatedEntity = CustomExtensions.ShallowCopyEntity<Customer>(old);
    
    updatedEntity.Name = "Modified";
    updatedEntity.MobileNo = "9999999999";
    
    // Copy the updated values back
    Mapper.Map(updatedEntity, entity);
    
    context.SaveChanges();
    

    选项2

    在最初加载的实体中进行更改,如果用户改变主意并取消,则将其丢弃。有关如何操作的信息,请参阅this帖子和this帖子。 丢弃整个DbContext可能不是一个很好的选择,如果你仍然需要它(呃)。