I\'ve been reading other questions on how to implement if-exists-insert-else-update semantics in EF, but either I\'m not understanding how the answers work, or they are in f
Just to add my way, not that it really deals with the annoyance of exceptions being thrown and transactions not quite cutting it as a scalable solution but it does avoid race conditions from causing problems where lock type solutions are not possible (easily managed) such as in distributed systems.
I very simply use the exception and try the insert first. I use a modification of your original code as an example:
using(var context = new MyEntities())
{
EntityEntry entityUser = null;
try
{
user = new User
{
// etc
};
entityUser = context.Users.Add(user);
context.SaveChanges(); // Will throw if the entity already exists
}
catch (DbUpdateException x)
when (x.InnerException != null && x.InnerException.Message.StartsWith("Cannot insert duplicate key row in object"))
{
if (entityUser != null)
{
// Detach the entity to stop it hanging around on the context
entityUser.State = EntityState.Detached;
}
var user = context.Users.Find(userId);
if (user != null) // just in case someone deleted it in the mean time
{
// update the user
user.property = newProperty;
context.SaveChanges();
}
}
}
It's not pretty, but it works and might be of use to someone.