无法附加实体框架6中的现有对象

本文关键字:对象 框架 实体 | 更新日期: 2023-09-27 18:04:34

我有一个类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"的实体。客户的失败,因为另一个相同类型的实体已经有相同的主键值。这可能发生在使用'Attach'方法或将实体的状态设置为"未更改"或"修改"(如果有)图中的实体具有冲突的键值。这可能是因为有些实体是新的,还没有收到数据库生成的键值。在这种情况下,使用'Add'方法或'Added'实体状态来跟踪图形,然后将非新实体的状态设置为"未修改"或"修改"视情况而定。

我试着将EntityState改为Modified,但它不起作用。

谁能告诉我如何实现这一点?

我的主要目标是

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

编辑

正如在这个评论中指出的,我试图附加已经存在于上下文中的对象。所以我可以先分离它,然后再附加,如下图所示,如果附加是强制性的。

        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();

否则我可以遵循这个答案中提到的两个选项

无法附加实体框架6中的现有对象

我能想到的有两个选择:

  1. 将更新的值复制回加载到DbContext中的原始实体,然后保存更改。
  2. 如果用户取消更新,则更新原始实体的值,然后丢弃它们。

选项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

在最初加载的实体中进行更改,如果用户改变主意并取消,则丢弃它们。关于如何做到这一点,请参阅这篇文章和这篇文章。丢弃整个DbContext可能不是一个好的选择,如果你仍然需要它(duh)。