Update Row if it Exists Else Insert Logic with Entity Framework
If you are working with attached object (object loaded from the same instance of the context) you can simply use:
if (context.ObjectStateManager.GetObjectStateEntry(myEntity).State == EntityState.Detached)
{
context.MyEntities.AddObject(myEntity);
}
// Attached object tracks modifications automatically
context.SaveChanges();
If you can use any knowledge about the object's key you can use something like this:
if (myEntity.Id != 0)
{
context.MyEntities.Attach(myEntity);
context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified);
}
else
{
context.MyEntities.AddObject(myEntity);
}
context.SaveChanges();
If you can't decide existance of the object by its Id you must execute lookup query:
var id = myEntity.Id;
if (context.MyEntities.Any(e => e.Id == id))
{
context.MyEntities.Attach(myEntity);
context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified);
}
else
{
context.MyEntities.AddObject(myEntity);
}
context.SaveChanges();
As of Entity Framework 4.3, there is an AddOrUpdate
method at namespace System.Data.Entity.Migrations
:
public static void AddOrUpdate<TEntity>(
this IDbSet<TEntity> set,
params TEntity[] entities
)
where TEntity : class
which by the doc:
Adds or updates entities by key when SaveChanges is called. Equivalent to an "upsert" operation from database terminology. This method can be useful when seeding data using Migrations.
To answer the comment by @Smashing1978, I will paste relevant parts from link provided by @Colin
The job of AddOrUpdate is to ensure that you don’t create duplicates when you seed data during development.
First, it will execute a query in your database looking for a record where whatever you supplied as a key (first parameter) matches the mapped column value (or values) supplied in the AddOrUpdate. So this is a little loosey-goosey for matching but perfectly fine for seeding design time data.
More importantly, if a match is found then the update will update all and null out any that weren’t in your AddOrUpdate.
That said, I have a situation where I am pulling data from an external service and inserting or updating existing values by primary key (and my local data for consumers is read-only) - been using AddOrUpdate
in production for more than 6 months now and so far no problems.
The magic happens when calling SaveChanges()
and depends on the current EntityState
. If the entity has an EntityState.Added
, it will be added to the database, if it has an EntityState.Modified
, it will be updated in the database. So you can implement an InsertOrUpdate()
method as follows:
public void InsertOrUpdate(Blog blog)
{
using (var context = new BloggingContext())
{
context.Entry(blog).State = blog.BlogId == 0 ?
EntityState.Added :
EntityState.Modified;
context.SaveChanges();
}
}
More about EntityState
If you can't check on Id = 0
to determine if it's a new entity or not, check the answer of Ladislav Mrnka.