什么是最有效的方法来实现更新行,如果它存在,否则插入新的行逻辑使用实体框架?或者这有什么规律吗?


当前回答

Ladislav的答案很接近,但我不得不做了一些修改,以使其在EF6(数据库优先)中工作。我用我的AddOrUpdate方法扩展了我的数据上下文,到目前为止,这似乎与分离的对象工作得很好:

using System.Data.Entity;

[....]

public partial class MyDBEntities {

  public void AddOrUpdate(MyDBEntities ctx, DbSet set, Object obj, long ID) {
      if (ID != 0) {
          set.Attach(obj);
          ctx.Entry(obj).State = EntityState.Modified;
      }
      else {
          set.Add(obj);
      }
  }
[....]

其他回答

试试这个算法

public void InsertOrUpdate(Item item) 
{ 
    using (var context = new ItemContext()) 
    { 
       var existedItem = context.Items.Where(x => x.Id==item.Id).FirstOrDefault();

       if(existedItem != null)
       {
          context.Entry(existedItem).CurrentValues.SetValues(item);
          
              //or only if you want to update some special properties
                existedItem.Prop1=item.Prop1;
                existedItem.Prop2=item.Prop2
                context.Entry(existedItem).State =EntityState.Modified;
              //-----------

       } 
       else 
       { 
        context.Items.Add(item);
       }

    context.SaveChanges();
   }
}

如果你正在使用附加对象(从上下文的同一个实例加载的对象),你可以简单地使用:

if (context.ObjectStateManager.GetObjectStateEntry(myEntity).State == EntityState.Detached)
{
    context.MyEntities.AddObject(myEntity);
}

// Attached object tracks modifications automatically

context.SaveChanges();

如果你可以使用任何关于对象键的知识,你可以使用这样的东西:

if (myEntity.Id != 0)
{
    context.MyEntities.Attach(myEntity);
    context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified);
}
else
{
    context.MyEntities.AddObject(myEntity);
}

context.SaveChanges();

如果你不能通过Id判断对象是否存在,你必须执行查找查询:

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();

Ladislav的答案很接近,但我不得不做了一些修改,以使其在EF6(数据库优先)中工作。我用我的AddOrUpdate方法扩展了我的数据上下文,到目前为止,这似乎与分离的对象工作得很好:

using System.Data.Entity;

[....]

public partial class MyDBEntities {

  public void AddOrUpdate(MyDBEntities ctx, DbSet set, Object obj, long ID) {
      if (ID != 0) {
          set.Attach(obj);
          ctx.Entry(obj).State = EntityState.Modified;
      }
      else {
          set.Add(obj);
      }
  }
[....]

纠正

public static void InsertOrUpdateRange<T, T2>(this T entity, List<T2> updateEntity) 
        where T : class
        where T2 : class
        {
            foreach(var e in updateEntity)
            {
                context.Set<T2>().InsertOrUpdate(e);
            }
        }


        public static void InsertOrUpdate<T, T2>(this T entity, T2 updateEntity) 
        where T : class
        where T2 : class
        {
            if (context.Entry(updateEntity).State == EntityState.Detached)
            {
                if (context.Set<T2>().Any(t => t == updateEntity))
                {
                   context.Set<T2>().Update(updateEntity); 
                }
                else
                {
                    context.Set<T2>().Add(updateEntity);
                }

            }
            context.SaveChanges();
        }

使用Any检查现有行。

public static void insertOrUpdateCustomer(Customer customer)
{
    using (var db = getDb())
    {

        db.Entry(customer).State = !db.Customer.Any(f => f.CustomerId == customer.CustomerId) ? EntityState.Added : EntityState.Modified;
        db.SaveChanges();

    }

}