【问题标题】: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 进行通用保存的问题:stackoverflow.com/questions/6018711/… 其结果是编写通用保存方法(根据需要插入或更新)。它很快就会变得一团糟。

标签: sql optimization entity-framework-4 sql-update


【解决方案1】:

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

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

【讨论】:

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

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

using (var context = new TestStackOverFlowEntities())
{
    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 TestStackOverFlowEntities())
{
    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);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    相关资源
    最近更新 更多