【问题标题】:LINQ To SQL exception with Attach(): Cannot add an entity with a key that is already in use带有 Attach() 的 LINQ To SQL 异常:无法使用已在使用的键添加实体
【发布时间】:2010-12-18 00:14:59
【问题描述】:

考虑这个典型的断开连接的场景:

  • 使用 LINQ To SQL 从 SQL Server 加载客户对象
  • 用户编辑实体,表示层发回修改的实体。
  • 使用 L2S 的数据层必须将更改发送到 SQL Server

考虑这个旨在获取客户实体的 LINQ To SQL 查询。

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: Cannot add an entity with a key that is already in use.

问题

  • 如何避免此异常?
  • 更新没有/不想要/不需要时间戳属性的实体的最佳策略是什么?

次优解决方法

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

【问题讨论】:

    标签: c# linq-to-sql concurrency datacontext


    【解决方案1】:

    这与您的数据上下文 (db) 无法多次跟踪同一实体有关。有关正在发生的事情的更多详细信息,请参阅this post

    该帖子底部的一个不起眼的 cmets 说要尝试:

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

    让我知道它对你有用,因为那篇文章的 OP 说它对他有用...

    【讨论】:

    • +1;谢谢!那确实奏效了!我暂时不回答这个问题,但这个答案肯定能解决问题!
    • 正如 JustLoren 所说,Attach 是为了给上下文提供一个它还没有的实体——它不能用来替换一个。在典型情况下,如果您要取回一个对象,则它会在稍后的某个时间被附加到一个新的数据上下文中。
    【解决方案2】:

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

    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
    }
    

    【讨论】:

    • 这不会更新数据库,它只会更改变量 oldCustomer 所指的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多