如何在ADO.NET EF 4.1中插入记录?

我正在尝试完成一些非常简单的事情,但我无法使用Entity Framework 4.1找到它。

我想要一个接受一个对象然后执行UPSERT的控制器方法(根据数据库中是否存在记录,插入或更新)。

我使用的是自然键,所以我无法查看我的POCO并告诉它是否是新的。

这就是我这样做的方式,对我来说似乎不对:

[HttpPost] public JsonResult SaveMyEntity(MyEntity entity) { MyContainer db = new MyContainer(); // DbContext if (ModelState.IsValid) { var existing = db.MyEntitys.Find(entity.MyKey); if (existing == null) { db.MyEntitys.Add(entity); } else { existing.A = entity.A; existing.B = entity.B; db.Entry(existing).State = EntityState.Modified; } db.SaveChanges(); return Json(new { Result = "Success" }); } } 

理想情况下,整个事情就是这样:

 db.MyEntities.AddOrModify(entity); 

遗憾的是,如果不查询数据库或使用存储过程,则无法执行此操作。 简约代码应该是:

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

在大多数情况下,除非您已禁用更改跟踪,否则无需显式设置EntityState.Modified

我们采用的解决方案是检查实体标识符的值:

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

实际上有一种方法来信息数据库上下文,您尝试插入的实体已更改,现在是新的实体

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

要执行UPSERT操作,您可能需要考虑创建执行MERGE的SP。

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

无论你选择哪种方式,操作必须是primefaces的,否则你就会遇到竞争条件。 你的SP可能需要一个HOLDLOCK来取消这个……

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

我知道这个问题已经过时并且有一个可接受的答案,但我认为有一个更好的解决方案:它不需要实现额外的接口或定义键类型。

 public static class DbSetExtensions { public static EntityEntry AddIfNotExists(this DbSet dbSet, TEnt entity, Func predicate) where TEnt : class { var exists = dbSet.Any(c => predicate(entity).Equals(predicate(c))); return exists ? null : dbSet.Add(entity); } public static void AddRangeIfNotExists(this DbSet dbSet, IEnumerable entities, Func 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)); } } 

所以稍后它可以像这样使用:

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