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


当前回答

纠正

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

其他回答

神奇的是在调用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的答案。

在我看来,有了新发布的EntityGraphOperations for Entity Framework Code First,你可以省去为定义图中所有实体的状态而编写一些重复的代码。我是这个产品的作者。我已经在github、code-project(包括一步一步的演示和一个示例项目,可以下载)和nuget上发布了它。

它将自动将实体的状态设置为已添加或已修改。如果它不再存在,您将手动选择必须删除哪些实体。

示例:

假设我有一个Person对象。一个人可以有很多电话,一个文件,也可以有一个配偶。

public class Person
{
     public int Id { get; set; }
     public string FirstName { get; set; }
     public string LastName { get; set; }
     public string MiddleName { get; set; }
     public int Age { get; set; }
     public int DocumentId {get; set;}

     public virtual ICollection<Phone> Phones { get; set; }
     public virtual Document Document { get; set; }
     public virtual PersonSpouse PersonSpouse { get; set; }
}

我想确定图中包含的所有实体的状态。

context.InsertOrUpdateGraph(person)
       .After(entity =>
       {
            // Delete missing phones.
            entity.HasCollection(p => p.Phones)
               .DeleteMissingEntities();

            // Delete if spouse is not exist anymore.
            entity.HasNavigationalProperty(m => m.PersonSpouse)
                  .DeleteIfNull();
       });

另外,如你所知,在定义电话实体的状态时,唯一的键属性可以发挥作用。出于这种特殊目的,我们有ExtendedEntityTypeConfiguration<>类,它继承自EntityTypeConfiguration<>。如果我们想使用这样的特殊配置,那么我们必须从ExtendedEntityTypeConfiguration<>继承我们的映射类,而不是EntityTypeConfiguration<>。例如:

public class PhoneMap: ExtendedEntityTypeConfiguration<Phone>
    {
        public PhoneMap()
        {
             // Primary Key
             this.HasKey(m => m.Id);
              …
             // Unique keys
             this.HasUniqueKey(m => new { m.Prefix, m.Digits });
        }
    }

这是所有。

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

    }

}

纠正

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

试试这个算法

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