The code listed below attempts to update a row in the database, but throws an exception instead:
System.Data.Linq.DuplicateKeyException:
Cannot add an entity with a key that
is already in use
Most examples I’ve seen query the database to obtain an instance of an entity, modify some of the instance’s properties, and then update it. Here I’m getting the object from a different source entirely (it’s being parsed from an XML file) and querying to see if there’s already a row for this data. If there is, I’m setting the primary key and attempting to run an update. What’s the correct way to do this?
Here’s the trimmed down version of the code:
Customer customer = new Customer(); // Customer has a database generated
// identity column called CustomerId
// populate customer object
customer.Name = "Mr. X";
customer.Email = "x@company.com";
// etc.
// is customer already in database?
// identify customer by email
var results = ctx.Where(c => c.Email == customer.Email); // ctx is a DataContext
if (results.Any())
{
Customer existing = results.Single();
// set primary key to match existing one
customer.CustomerId = existing.CustomerId;
// update database
customerTable.Attach(customer); // customerTable is a Table<Customer>
ctx.SubmitChanges();
}
// otherwise do insert
// ...
Apparently this is not a new problem. Here’s a sampling of some of the posts that discuss this issue:
http://www.west-wind.com/weblog/posts/134095.aspx
http://www.codeproject.com/KB/linq/linq-to-sql-detach.aspx
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/3848c02c-464e-40ff-87b6-813bff7b1263/
I got it working by creating a new DataContext and Table before doing the update. My modified code looks like this:
The way I understand this is that the DataContext can only contain one instance of each unique entity. Attempting to attach a new entity with the same primary key causes the error, as there will now be two instances of the same entity. The new DataContext does not know about the existing entity and so has no problem attaching the new one.
UPDATE: It looks like this question has already been answered.
UPDATE: Don’t use my sample code as-is. It caused me other problems.