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

爷,独闯天下 提交于 2019-11-30 11:56:19

Unfortunately there is no way to do this without querying database or using stored procedure. The minimalistic code should be:

public void AddOrModify<T>(T entity, string key) where T : class, IEntity // Implements MyKey 
{
     using (var context = new MyContainer())
     {
         if (context.Set<T>().Any(e => e.MyKey == key))
         {
              context.Entry(entity).State = EntityState.Modified;
         } 
         else
         {
              context.Entry(entity).State = EntityState.Added;
         }

         context.SaveChanges();
     }
}

In most cases you do not need to explicitly set the EntityState.Modified unless you've disabled change tracking.

The solution we took was to check the value of the entity identifier:

if (entity.Id == default(int)) {
    // transient entity so insert
} else {
    // update
}

actually there is a way to informa db context that entity you are trying to insert is changed and now the new one

_context.MyEntity.Attach(entity);
_context.MyEntity(entity).State = System.Data.EntityState.Modified;

To perform an UPSERT operation, You might want to consider creating an SP that performs a MERGE.

http://www.databasejournal.com/features/mssql/article.php/3739131/UPSERT-Functionality-in-SQL-Server-2008.htm

Whatever way you choose the operation must be atomic or you'll have a race condition. Your SP will probably need a HOLDLOCK to void this ...

http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx

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();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!