1

I know it can be silly question, but although ...

Im learning ASP.NET MVC 4 and got one question about the dbcontext.Entry method, lets assume we got such method :

public ActionResult Edit(Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

How the db.Entry(movie) determine which exactly row from the database is this "movie" instance? If all properties of this movie parameter object will be changed, how will it be possible to determine which row this instance should be attached to? I got smth on my head like it will determine by the Id which we cant change but not sure, so better if I ask :)

CSharpBeginner
  • 1,625
  • 5
  • 22
  • 36
  • I am putting my comment here instead of as an Answer since I am not sure I will completely resolve your question. You ask in your post "if all properties...change, how to determine which row". The important thing to remember is that the primary key of your object should never change, so determining the proper row is easy. (There may be valid use cases when the key could change...but that is very, very rare.) – Jason Aug 15 '14 at 13:22
  • Thank you for your response Jason, yes your are absolutely correct, but the reason I have had such problem was I didn't know I shouldnt/cant change Primary Key in EF:) Now as I know it becomes pretty clearly for me, anyway thanks for your answer, cheers ! :) – CSharpBeginner Aug 18 '14 at 16:21
  • Not changing your PK is not strictly limited to EF...that is true of any place where you are storing data (SQL, Oracle, XML files, csv files, whatever. If you create an object (or entity or whatever) and it is given a unique identifier, then that identifier should last forever. – Jason Aug 18 '14 at 16:58

3 Answers3

1

When EF generates the models it includes information on what column is the primary key in the database. db.Entry(model) binds the model to the context using that primary key and whatever primary key it shares in the database will be overwriten by the data in the model when SaveChanges() is called. If the primary key is 0, or empty you must set the State to EntityState.Added instead of EntityState.Modified.

As another answer said this can fail. The reason that binding can fail is that a context can only track a single distinct entity once (entity being a distinct class and id). If you attempt to do the following you'll get an exception:

var dbModel = db.Movie.Find(movie.ID);
db.Entry(movie.ID) // Doesn't matter what you do, this will always fail 

Because the db context is already tracking a Movie with the same ID.

This is one of the larger reasons that you don't want to share db contexts between users, because another user attempting to update the same entry will cause the second one to throw an exception. While the transaction will be ACID, you can end up with edge case race conditions (for lack of a better term) between users.

siva.k
  • 1,344
  • 14
  • 24
  • @CSharpBeginner Related if you want to see a way to squeeze some performance out of EF check out this on how you can share context between controllers for the same request: http://www.codefall.io/1-aug-2014/tuning-entityframework--keeping-the-context-alive-to-save-overhead.html (full disclosure, this is me too). – siva.k Aug 15 '14 at 13:35
0

This method has a parameter Movie, but it has nothing to do with database. You must update object that you will get from db like:

public ActionResult Edit(Movie updatedMovie)
{
  if (ModelState.IsValid)
  {
   //db=your entities context
   //here you will get instance of record from db that you want to update
   Movie movie = db.Movie.Find(updatedMovie.Id);
   TryUpdateModel(movie);
   ctx.SaveChanges();
   return RedirectToAction("Index");
  }
  return View(movie);
}

Maybe there is more efficient way , but I'm using it like this and it works fine.

If code in your question is a version that is supposed to be a working version, then it wasn't working for me when I have been trying to solve a similar problem so I had to solve it by using code above finally.

BblackK
  • 524
  • 1
  • 8
  • 25
  • It is just another possible way how to do it. For me, the version with `db.Entry` didn't worked when I was trying to solve similar problem. – BblackK Aug 15 '14 at 13:16
0

Every Table that used by EF must have a Primary key, unless it is a collection , so the EF know the row by the primary key that stay the same.

sino
  • 754
  • 1
  • 7
  • 22
  • You cant Change the Primary Key (ID) . http://stackoverflow.com/questions/1367751/update-primary-key-value-using-entity-framework – sino Aug 15 '14 at 16:04