可以 EntityState.Modified 导致执行插入操作

Could EntityState.Modified cause Insert operation to be performed

我正在阅读以下关于 entity framework 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);
}

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

这是否意味着

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

如果 Instructor 没有 prevouse OfficeAssignment 对象,将导致对 OfficeAssignment 记录执行插入语句?管理它的规则是什么?

这是完整的模型图:-

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

A. 将其直接添加到 Dbset 中,并添加您希望它具有的其他关系。

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

B. 将其附加到现有实体,如果该实体 is/was 未跟踪,则将该实体标记为“已修改”。

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

你问题中给出的方式是第二种方式。这一切都是为了让 "new" 对象出现在代表您的数据库中所有被跟踪的 EF 实体的对象图中。

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

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

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

您将在实体上设置一个标志,表明它已被更改。当调用 SaveChanges 方法时,Modified 标志导致 Entity Framework 创建 SQL 语句来更新数据库行。数据库行的所有列都将更新,包括用户未更改的列,并发冲突将被忽略。为了更好地理解发生了什么,您可以将 Instructor 实例看成一棵树。 Code First 认识到您有导航 属性,因此需要更新或插入(视情况而定)。如果 OfficeAssignmentdefault(int)Id 不同(我认为这是一个整数),那么它将被更新,在其他情况下,它将被插入。

是的,可以加载 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();
}