EntityState.Modified会导致执行插入操作

时间:2015-01-12 02:37:22

标签: c# asp.net-mvc entity-framework ado.net entity-framework-6

我正在阅读以下有关实体框架6 Link的教程。在名为“为教师添加编辑页面”的部分中,作者在Post编辑操作方法中编写了以下代码: -

[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    var instructorToUpdate = db.Instructors
       .Include(i => i.OfficeAssignment)
       .Where(i => i.ID == id)
       .Single();

    if (TryUpdateModel(instructorToUpdate, "",
       new string[] { "LastName", "FirstMidName", "HireDate", "OfficeAssignment" }))
    {
       try
       {
          if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment.Location))
          {
             instructorToUpdate.OfficeAssignment = null;
          }

          db.Entry(instructorToUpdate).State = EntityState.Modified;
          db.SaveChanges();

          return RedirectToAction("Index");
       }
       catch (RetryLimitExceededException /* dex */)
      {
         //Log the error (uncomment dex variable name and add a line here to write a log.
         ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
      }
   }
   return View(instructorToUpdate);
}

此代码将涵盖以下三个条件: -

  • 如果用户清除了办公室分配并且它最初有值,则必须删除并删除OfficeAssignment实体。
  • 如果用户输入了办公室分配值且它最初为空,则必须创建一个新的OfficeAssignment实体。
  • 如果用户更改了办公室分配的值,则必须更改现有OfficeAssignment实体中的值。

这是否意味着

db.Entry(instructorToUpdate).State = EntityState.Modified;

是否会导致对OfficeAssignment记录执行insert语句,因为教师没有主要的OfficeAssignment对象?什么是治理这个的规则?

这是完整的模型图: - enter image description here

3 个答案:

答案 0 :(得分:1)

基本上有两种方法可以通过EF保持实体。

A. :将其直接添加到Dbset,并附加您希望拥有的附加关系。

Entity e = new Entity();
e.ForeignEntityId = 123;
context.Entities.Add(e);
context.SaveChanges();

B。将其附加到现有实体,如果该实体未被跟踪,请将该实体标记为“已修改。”

Entity e = new Entity();
ForeignEntity fe = context.Find(...);
//Only needed if 'fe' was untracked
//context.Entry(fe).State = EntityState.Modified; 
fe.Entity = e;
context.SaveChanges();

问题中提出的方式是第二种方式。所有这些都是为了让“新”对象出现在对象图中,该对象图表示数据库中所有被跟踪的EF实体。

答案 1 :(得分:1)

DbContext.Entry方法用于执行显式加载,这意味着它可让您访问DbContext有关实体的所有信息。这超出了存储在实际实体属性中的值,包括诸如实体状态之类的内容以及从数据库中检索每个属性时的原始值。

当您调用TryUpdateModel方法时,它将使用模型绑定器中的值更新属性(您将其名称作为参数传递)。其中一个属性是OfficeAssignment,它也会更新。如果您认为自己没有输入Location,那么您就没有理由创建新OfficeAssigment(您需要做的{{1}因为即使您没有输入新的instructorToUpdate.OfficeAssignment = null;,也会有Location的实例。如果您添加新的OfficeAssignment,则会创建新的Location,如果您修改了OfficeAssignment,那么您将修改其值。 当你这样做时:

Location

您将在实体上设置一个标志,表明它已被更改。调用db.Entry(instructorToUpdate).State = EntityState.Modified; 方法时,SaveChanges标志会导致实体框架创建SQL语句以更新数据库行。将更新数据库行的所有列,包括用户未更改的那些列,并忽略并发冲突。为了更好地理解发生的事情,您可以像树一样查看Modified实例。 Code First识别您有一个navegation属性,因此需要更新或插入(取决于具体情况)。如果InstructorOfficeAssignmentId个不同(我正在压缩这是一个整数),那么它会被更新,而在其他情况下,它会被插入

答案 2 :(得分:0)

是的,可以加载DbContext.Entry方法,并且可以用于执行上述显式加载

我建议您执行“删除并插入”,直到您没有实时修改需求为止。

{
  //Remove existing data           
  modelname existingobj = dbobj.tablename.Find(id);        
  dbobj.tablename.Remove(existingobj);
  dbobj.SaveChanges();

  //Add data
  dbobj.Entry(existingobj).State = EntityState.Added;         
  dbobj.SaveChanges();
}