C# 附加()的LINQ到SQL异常:无法添加键已在使用的实体

C# 附加()的LINQ到SQL异常:无法添加键已在使用的实体,c#,linq-to-sql,concurrency,datacontext,C#,Linq To Sql,Concurrency,Datacontext,考虑这种典型的断开连接情况: 使用LINQ到SQL从SQL Server加载客户对象 用户编辑实体,表示层发回修改后的实体 使用L2S的数据层必须将更改发送到SQL Server 考虑这个linqtosql查询,其目的是获取一个客户实体 Cust custOrig = db.Custs.SingleOrDefault(o => o.ID == c.ID); //get the original db.Custs.Attach(c, custOrig); //we don't have

考虑这种典型的断开连接情况:

  • 使用LINQ到SQL从SQL Server加载客户对象
  • 用户编辑实体,表示层发回修改后的实体
  • 使用L2S的数据层必须将更改发送到SQL Server
考虑这个linqtosql查询,其目的是获取一个客户实体

Cust custOrig = db.Custs.SingleOrDefault(o => o.ID == c.ID); //get the original
db.Custs.Attach(c, custOrig); //we don't have a TimeStamp=True property
db.SubmitChanges();                
DuplicateKeyException:无法添加具有已在使用的密钥的实体。

问题

  • 如何避免这种例外情况
  • 更新没有/想要/需要时间戳属性的实体的最佳策略是什么
次优解决方案

  • 手动将更新的客户中的每个属性设置为原始客户
  • 启动另一个DataContext

这与datacontext(db)不能多次跟踪同一实体有关。有关正在发生的情况的更多详细信息,请参阅

在那篇文章的底部有一条模糊的评论说,试试看:

public void Update(Customer customer)
{
  NorthwindDataContext context = new NorthwindDataContext();
  context.Attach(customer);
  context.Refresh(RefreshMode.KeepCurrentValues, customer);
  context.SubmitChanges();
}

让我知道它对你有什么作用,因为那篇文章的专栏说它对他有作用…

你可以这样做,而不是创建一个新的上下文:

public void Update(Customer customer)
{
    Customer oldCustomer= db.Custs.First(c => c.ID == customer.ID);  //retrieve unedited 
    oldCustomer = customer;  // set the old customer to the new customer.
    db.SubmitChanges();  //sumbit to database
}

+1; 谢谢那确实有效!我暂时不回答这个问题,但这个答案肯定能解决问题!正如JustLoren所说,Attach是用来给上下文提供一个它还没有的实体的,它不能用来代替一个实体。在典型的情况下,如果您要取回一个对象,它将在稍后某个时间被附加到一个新的数据上下文。这不会更新数据库,它只会更改变量oldCustomer引用的内容。