LINQ To SQL изключение с Attach(): Не може да се добави обект с ключ, който вече се използва

Помислете за този типичен сценарий с прекъсната връзка:

  • заредете клиентски обект от SQL Server с помощта на LINQ към SQL
  • потребителят редактира обекта и нивото на представяне изпраща обратно модифицирания обект.
  • слоят данни, използвайки L2S, трябва да изпрати промените на SQL Server

Помислете за тази LINQ към 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.

алт текст

Въпрос

  • Как можете да избегнете това изключение?
  • Коя е най-добрата стратегия за актуализиране на обект, който НЕ притежава/иска/не се нуждае от свойство timestamp?

Неоптимални заобиколни решения

  • ръчно настройте всяко свойство в актуализирания клиент на оригиналния клиент.
  • завъртете друг DataContext

person p.campbell    schedule 18.11.2009    source източник


Отговори (2)


Това е свързано с факта, че вашият контекст на данни (db) не може да проследява един и същ обект повече от веднъж. Вижте тази публикация за повече подробности относно случващото се.

Един от неясните коментари в долната част на тази публикация казва да опитате:

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

Кажете ми как работи за вас, тъй като OP на тази публикация казва, че се е получило за него...

person JustLoren    schedule 18.11.2009
comment
+1; Благодаря! Това наистина свърши работа! Засега ще оставя този въпрос „без отговор“, но този отговор определено решава проблема! - person p.campbell; 18.11.2009
comment
Както казва JustLoren, Attach е там, за да даде на контекст обект, който той все още няма - не може да се използва за заместване на такъв. В типична ситуация, ако получавате обект обратно, той е по-късно и ще бъде прикачен към нов контекст на данни. - person DamienG; 19.11.2009

Вместо да създавате нов контекст, можете да направите това:

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
}
person Jostein Lie Sand    schedule 17.07.2012
comment
Това няма да актуализира базата данни, а просто ще промени това, към което се отнася променливата oldCustomer. - person Haukman; 03.11.2012