Could EntityState.Modified cause Insert operation to be performed

ado.net asp.net-mvc c# entity-framework entity-framework-6

Question

I am reading the following tutorial about entity framework 6 Link. And inside the section named ”Adding an Edit Page for Instructors”, the author wrote the following code inside the Post edit action method:-

[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);
}

This code will cover these three conditions:-

  • If the user clears the office assignment and it originally had a value, you must remove and delete the OfficeAssignment entity.
  • If the user enters an office assignment value and it originally was empty, you must create a new OfficeAssignment entity.
  • If the user changes the value of an office assignment, you must change the value in an existing OfficeAssignment entity.

So does this means that

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

will cause an insert statement to be performed for the OfficeAssignment record incase the Instructor did not have a prevouse OfficeAssignment object ? and what is the rule that govern this ?

here is the complete model diagram:- enter image description here

1
3
1/12/2015 2:37:21 AM

Accepted Answer

DbContext.Entry method is used to do an explicit loading, that means that It gives you access to all the information that the DbContext has about an entity. This goes beyond the values that are stored in the properties of the actual entity and includes things such as the state of the entity and the original values for each property when it was retrieved from the database.

When you call the TryUpdateModel method, it will update the properties (that you pass their names as a parameter) with values from the model binder. One of these properties is OfficeAssignment, wich is updated too. If in your view you don't enter a Location, then you don't have reason to create a new OfficeAssigment (that's way you need to do instructorToUpdate.OfficeAssignment = null; because even when you don't enter a new Location, you will have a instance of OfficeAssignment). If you add a new Location, you are going to create a new OfficeAssignment, and if you modified the Location, then you are going to modified its value. When you do this:

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

You are going to set a flag on the entity indicating it has been changed. When the SaveChanges method is called, the Modified flag causes the Entity Framework to create SQL statements to update the database row. All columns of the database row will be updated, including those that the user didn't change, and concurrency conflicts are ignored. To understand better what happend, you can look the Instructor instance like a tree. Code First recognizes that you have a navegation property, so it need to be updated or insterted(depending on the case). If the OfficeAssignment have an Id different of the default(int) (I'm pressuming that is an interger), then it will be updated, and in other case, it will be inserted.

1
1/12/2015 3:22:57 PM

Popular Answer

There are basically two ways an entity can be persisted through EF.

A. Add it directly to the Dbset with the additional relationships you want it to have.

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

B. Attach it to an existing entity and if that entity is/was untracked, mark that entity as `Modified.

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

The way presented in your question is the second way. It's all about getting the "new" object to be present in the object graph that represents all tracked EF entities from your DB.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow