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


当前回答

神奇的是在调用SaveChanges()时发生的,这取决于当前的EntityState。如果实体有一个EntityState。如果它有一个EntityState,那么它将被添加到数据库中。修改后,将在数据库中更新。所以你可以实现InsertOrUpdate()方法,如下所示:

public void InsertOrUpdate(Blog blog) 
{ 
    using (var context = new BloggingContext()) 
    { 
        context.Entry(blog).State = blog.BlogId == 0 ? 
                                   EntityState.Added : 
                                   EntityState.Modified; 

        context.SaveChanges(); 
    } 
}

更多关于EntityState的信息

如果你不能检查Id = 0来确定它是否是一个新实体,请检查Ladislav Mrnka的答案。

其他回答

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

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

试试这个算法

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

如果你知道你正在使用相同的上下文并且没有分离任何实体,你可以像这样创建一个通用版本:

public void InsertOrUpdate<T>(T entity, DbContext db) where T : class
{
    if (db.Entry(entity).State == EntityState.Detached)
        db.Set<T>().Add(entity);

    // If an immediate save is needed, can be slow though
    // if iterating through many entities:
    db.SaveChanges(); 
}

Db当然可以是一个类字段,或者方法可以是静态的和一个扩展,但这是基本的。

神奇的是在调用SaveChanges()时发生的,这取决于当前的EntityState。如果实体有一个EntityState。如果它有一个EntityState,那么它将被添加到数据库中。修改后,将在数据库中更新。所以你可以实现InsertOrUpdate()方法,如下所示:

public void InsertOrUpdate(Blog blog) 
{ 
    using (var context = new BloggingContext()) 
    { 
        context.Entry(blog).State = blog.BlogId == 0 ? 
                                   EntityState.Added : 
                                   EntityState.Modified; 

        context.SaveChanges(); 
    } 
}

更多关于EntityState的信息

如果你不能检查Id = 0来确定它是否是一个新实体,请检查Ladislav Mrnka的答案。

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);
      }
  }
[....]