更新行,如果它存在Else插入逻辑与entity framework

有没有人有最有效的方式来实现“更新行,如果存在其他插入”逻辑使用entity framework的build议?

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

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

从Entity Framework 4.3起,在名称空间System.Data.Entity.Migrations有一个AddOrUpdate方法:

 public static void AddOrUpdate<TEntity>( this IDbSet<TEntity> set, params TEntity[] entities ) where TEntity : class 

这由doc :

调用SaveChanges时,按键添加或更新实体。 相当于数据库术语中的“upsert”操作。 在使用Migrations进行数据种植时,此方法非常有用。


要回答@ Smashing1978的评论 ,我会粘贴@Colin提供的链接的相关部分

AddOrUpdate的工作是确保在开发过程中为种子数据创build重复项。

首先,它会在你的数据库中执行一个查询,查找一个logging,无论你作为关键字(第一个参数)提供的是否与AddOrUpdate中提供的映射列值(或值)相匹配。 所以这是一个有点松散goosey匹配,但完全罚款播种devise时间数据。

更重要的是,如果find匹配项,则更新将更新所有不在AddOrUpdate中的任何项。

也就是说,我有一种情况,即从外部服务中提取数据,并通过主键插入或更新现有值(而我的本地数据是消费者是只读的) – 在生产中使用AddOrUpdate超过6个月,到目前为止没有问题。

如果你知道你正在使用相同的上下文而不是分离任何实体,你可以使用这样的通用版本:

 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当然可以是一个类字段,或者方法可以做成静态和扩展名,但这是基本的。

拉迪斯拉夫的答案很接近,但我不得不做一些修改,以使其在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); } } [....] 

当调用SaveChanges()并且依赖于当前的EntityState时,会发生EntityState 。 如果实体有一个EntityState.Added ,它将被添加到数据库中,如果它有一个EntityState.Modified ,它将在数据库中被更新。 所以你可以实现一个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的答案 。

插入else更新

 public void InsertUpdateData() { //Here TestEntities is the class which is given from "Save entity connection setting in web.config" TestEntities context = new TestEntities(); var query = from data in context.Employee orderby data.name select data; foreach (Employee details in query) { if (details.id == 1) { //Assign the new values to name whose id is 1 details.name = "Sanjay"; details. Surname="Desai"; details.address=" Desiwadi"; } else if(query==null) { details.name="Sharad"; details.surname=" Chougale "; details.address=" Gargoti"; } //Save the changes back to database. context.SaveChanges(); } 

在我看来,值得一提的是,使用新发布的EntityGraphOperations for Entity Framework Code First,您可以避免编写一些重复的代码来定义图中所有实体的状态。 我是这个产品的作者。 我已经在github上发布了它, 代码项目 ( 包括一步一步的演示和一个示例项目已经准备好下载)和nuget 。

它会自动将实体的状态设置为已Added或已Modified 。 如果不存在,你将手动select哪些实体必须被删除。

例子:

比方说,我有一个Person对象。 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(); }); 

也正如你所知,唯一的关键属性可以发挥作用,同时定义电话实体的状态。 为了这样的特殊目的,我们有了从EntityTypeConfiguration<>inheritance的ExtendedEntityTypeConfiguration<>类。 如果我们想要使用这样的特殊configuration,那么我们必须从ExtendedEntityTypeConfiguration<>inheritance我们的映射类,而不是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 }); } } 

就这样。