How do I upsert a record in ADO.NET EF 4.1?

Viewed 13879

I'm trying to accomplish something really simple and I can't find how to do it using Entity Framework 4.1.

I want a controller method that accepts an object and then does an UPSERT (either an insert or update depending on whether the record exists in the database).

I am using a natural key, so there's no way for me to look at my POCO and tell if it's new or not.

This is how I am doing it, and it seems wrong to me:

[HttpPost]
public JsonResult SaveMyEntity(MyEntity entity)
{            
    MyContainer db = new MyContainer(); // DbContext
    if (ModelState.IsValid)
    {
        var existing =
            db.MyEntitys.Find(entity.MyKey);
        if (existing == null)
        {
            db.MyEntitys.Add(entity);
        }
        else
        {
            existing.A = entity.A;
            existing.B = entity.B;
            db.Entry(existing).State = EntityState.Modified;
        }
        db.SaveChanges();
        return Json(new { Result = "Success" });
    }
}

Ideally, the whole thing would just be something like this:

db.MyEntities.AddOrModify(entity);
5 Answers

I know this question is old and has an accepted answer, but I think there is a better solution: it doesn't require an extra interface to be implemented or key type to be defined.

public static class DbSetExtensions
{
    public static EntityEntry<TEnt> AddIfNotExists<TEnt, TKey>(this DbSet<TEnt> dbSet, TEnt entity, Func<TEnt, TKey> predicate) where TEnt : class
    {
        var exists = dbSet.Any(c => predicate(entity).Equals(predicate(c)));
        return exists
            ? null
            : dbSet.Add(entity);
    }

    public static void AddRangeIfNotExists<TEnt, TKey>(this DbSet<TEnt> dbSet, IEnumerable<TEnt> entities, Func<TEnt, TKey> predicate) where TEnt : class
    {
        var entitiesExist = from ent in dbSet
            where entities.Any(add => predicate(ent).Equals(predicate(add)))
            select ent;

        dbSet.AddRange(entities.Except(entitiesExist));
    }
}

So later it can be used like this:

using (var context = new MyDbContext())
{
    var user1 = new User { Name = "Peter", Age = 32 };
    context.Users.AddIfNotExists(user1, u => u.Name);

    var user2 = new User { Name = "Joe", Age = 25 };
    context.Users.AddIfNotExists(user2, u => u.Age);

    // Adds user1 if there is no user with name "Peter"
    // Adds user2 if there is no user with age 25
    context.SaveChanges();
}
Related