实体框架:更新实体,如果不存在则添加

Posted

技术标签:

【中文标题】实体框架:更新实体,如果不存在则添加【英文标题】:Entity Framework: Update entity or add if it doesn't exist 【发布时间】:2011-06-22 02:56:38 【问题描述】:

我有一个场景,如果实体存在,我必须更新它,如果不存在,我必须添加一个新实体。

我想为此执行一个方法(如果它是一次到服务器的旅行会很棒)。

在 EF 中有类似的东西吗?

现在我的代码如下所示:

var entity = db.Entities.FirstOrDefault(e => e.Id == myId);
if (entity == null)

    entity = db.Entities.CreateObject();
    entity.Id = myId;


entity.Value = "my modified value";

db.SaveChanges();

但我想避免第一次查询,像这样:

var entity = new Entity();
entity.Id = myId;
entity.Value = "my modified value";
db.AddOrAttach(entity);
db.SaveChanges();

有没有类似的?还是无论如何我都必须执行第一个查询?

谢谢

【问题讨论】:

看看我关于使用 EF 进行通用保存的问题:***.com/questions/6018711/… 其结果是编写通用保存方法(根据需要插入或更新)。它很快就会变得一团糟。 【参考方案1】:

不幸的是,无论如何,您都必须执行第一个查询。

一种选择是编写一个执行 T-SQL MERGE 的存储过程,然后将其映射到函数导入,尽管这需要您将实体的标量值作为参数传递(并支持导航属性会完成),但它会完成你所追求的。

【讨论】:

对于我遇到此问题的每个表来说,这将是太多的工作。如果这成为性能问题,也许我会这样做。【参考方案2】:

我在带有 EF 4 的 MVC 3 中为 editing 运行了一些快速测试代码,它似乎可以使用以下代码进行编辑:

using (var context = new Test***Entities())

    Person p = new Person();
    p.Id = long.Parse(collection["Id"]);
    p.FirstName = collection["FirstName"];
    p.LastName = collection["LastName"];
    context.People.Attach(p);
    context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Modified);
    context.SaveChanges();
    return RedirectToAction("Index");

编辑:我也检查了创建新对象,您需要更改它

context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Added);

当 Id == 0 //即新对象。

添加新的快速而肮脏的代码是这样的:

using (var context = new Test***Entities())

    Person p = new Person();                        
    p.Id = 0;
    p.FirstName = collection["FirstName"];
    p.LastName = collection["LastName"];
    context.People.Attach(p);
    context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Added);
    context.SaveChanges();
    return RedirectToAction("Index");

【讨论】:

您没有专注于主要问题。您的回复假定我知道是否要更新或插入。这个问题的整个想法是我不知道应该发生什么。 “我有一个场景,如果实体存在,我必须更新它,如果不存在,我必须添加一个新实体。” -- 我给你的样本处理了这个问题,但我假设 entityId 为 0 表示新添加的,> 0 表示现有的。这不适用于 GUID。 是的,但在我的情况下,我添加的元素有一个外键作为组合主键,因此它永远不会为零。如果我有零,我可以使用它而不是我的代码的第一个查询。 顺便说一句:我再次测试了其他东西,我有 System.Data.EntityState.Added 用于两种场景(即编辑和添加),它似乎工作正常。试试看。【参考方案3】:

如果您只是想限制代码以阐明您的控制器:

db.Attach(model);
db.SaveChanges(model);

如果实体键存在则更新,如果不存在则创建。

【讨论】:

以上是关于实体框架:更新实体,如果不存在则添加的主要内容,如果未能解决你的问题,请参考以下文章

需要使用实体框架将大量记录插入数据库

当实体的表还不存在时,实体框架的行为是啥?

添加 Mysql 实体框架时,Visual Studio 中的表“dbname.dbname.tablename”不存在错误

Symfony 3.4 - 如果在多对多关系上不存在,则持续存在

表 'DBNAME.dbo.TableNAME' 不存在 MySQL 的实体框架 6

如果记录存在于实体框架中,则不要插入子表使用id