【问题标题】:How to update related entities in Entity Framework如何更新实体框架中的相关实体
【发布时间】:2012-01-15 22:14:25
【问题描述】:

我有一个 MVC 项目并使用 Entity Framework Code First 和 POCO 对象作为数据库。例如:

public class ClassA
{
  public int? Id {get; set;}
  public string Name { get; set;}
  public virtual ClassB B {get; set;}
}

public class ClassB
{
  public int? Id {get;set;}
  public string Description {get;set;}
}

我有一个创建或编辑模型的 ActionResult。问题是当我调用此 ActionResult 更新模型时,model.B 已更改,关系未保存在数据库中。当调用 ActionResult 来创建一个新对象时,它会按预期工作。我该如何解决?

public ActionResult Save(ClassA model)
{
  model.B = GetBFromDb(model.B.Id.Value);

  if(ModelState.IsValid)
  {
    if (id.HasValue)
    {
      context.Entry(model).State = System.Data.EntityState.Modified;
    }
    else
    {
      context.ClassAs.Add(model);
    }
    context.SaveChanges();
    // redirect to index etc.
  }
  return View("EditForm", model);
}

【问题讨论】:

    标签: c# asp.net-mvc-3 entity-framework ef-code-first


    【解决方案1】:

    我通过将带有外键的ClassA 更改为ClassB 并设置BId 的值来解决它:

    public class ClassA
    {
      public int? Id {get; set;}
      public string Name { get; set;}
      public int BId {get;set;} // foreign key to B
      public virtual ClassB B {get; set;}
    }
    

    为什么这个外键属性代替了生成的 EF 外键来完成这项工作?

    【讨论】:

    • 在断开连接的情况下,当您没有外键时,EF 无法解决一些空白,您必须证明额外的代码。否则看不到关系。使用 FK 属性,它是一个标量值,EF 更容易跟踪跨进程。实际上,我写了关于这个确切主题的 2012 年 1 月数据点专栏!当您拥有 FK 标量属性时,EF 更容易使用。否则,您希望“正常工作”的许多功能无法&它迫使您更好地了解正在发生的事情以及如何提供所需的信息。抱歉,我之前没有看到丢失的 FK
    【解决方案2】:

    你不能简单地调用:

    context.Entry(model).State = System.Data.EntityState.Modified;
    

    必须首先从上下文中检索实体,以便 EF 可以开始跟踪它。然后,您需要在调用 context.SaveChanges() 之前对该实体应用任何更改。

    var entity = context.ClassAs.Find(model.Id);
    
    // set properties you want to modify on entity
    entity.Name = model.Name;
    entity.ClassB = context.ClassBs.Find(model.ClassB.Id);
    // other changes to entity as required...
    
    context.SaveChanges();
    

    EF 以这种方式跟踪 entity 并知道对其应用更新。

    【讨论】:

    • 感谢这项工作!我如何设置entity.ClassB = null;?似乎只是将其设置为 null 是行不通的。
    • Yuck... context.Entry(model).State 将导致上下文查看模型是否正在被跟踪,如果不是,它将开始跟踪它。您不必执行另一个数据库查询来跟踪模型实例。 Henkie 对该 ocde 的问题是,该方法只会更改设置传入实体的状态。“修改”状态设置不会应用于图表的其余部分。
    • @JulieLerman 谢谢我发现一些教程也将状态设置为已修改。但是我仍然有我的关系不会更新的问题。
    • 我误读了@JulieLerman 的评论,认为她不关心 context.Entry(model).State 方法,因为开头是 Yuck 这个词,我意识到更多的关注Yuck 是回答者的名字!重读,我相信使用 context.Entry(model).State 是理想的方法。也许在 Yuck 之前添加 @ 是个好主意。
    • 大声笑!我只是以同样的方式阅读它,因为两年后,它对我来说已经断章取义了。哈哈!好收获
    【解决方案3】:

    如果您附加然后将状态设置为修改后的实体框架将发送所有属性进行更新。您不必在下面采用 otter 方法,因为这会导致发生整个单独的负载。如果您这样做,则传递模型没有任何意义,只有一个 id,然后您调用 TryUpdateModel 来填写表单中的属性。

    就个人而言,此处修改的附件更简洁,因为加载数据不需要完整的往返

    http://geekswithblogs.net/michelotti/archive/2009/11/27/attaching-modified-entities-in-ef-4.aspx

    【讨论】:

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