C# ASP.NET应用程序中的EF dbcontext.Entry

C# ASP.NET应用程序中的EF dbcontext.Entry,c#,asp.net,asp.net-mvc,entity-framework,asp.net-mvc-4,C#,Asp.net,Asp.net Mvc,Entity Framework,Asp.net Mvc 4,我知道这可能是个愚蠢的问题,但尽管 我正在学习ASP.NET MVC 4,有一个关于dbcontext.Entry方法的问题,假设我们有这样的方法: public ActionResult Edit(Movie movie) { if (ModelState.IsValid) { db.Entry(movie).State = EntityState.Modified; db.SaveChanges(); return Redire

我知道这可能是个愚蠢的问题,但尽管

我正在学习ASP.NET MVC 4,有一个关于dbcontext.Entry方法的问题,假设我们有这样的方法:

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

db.Entry(movie)如何确定数据库中的哪一行是这个“movie”实例?如果此movie parameter对象的所有属性都将更改,如何确定此实例应附加到哪一行?我头上有一个smth,好像它将由Id决定,我们不能更改但不能确定,所以如果我问:)

这个方法有一个参数
Movie
,但它与数据库无关。您必须更新将从db获得的对象,如:

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);
}
也许有更有效的方法,但我就是这样用的,效果很好


如果您的问题中的代码是一个应该是工作版本的版本,那么当我试图解决类似问题时,它对我不起作用,所以我最终必须使用上面的代码来解决它。

EF使用的每个表都必须有一个主键,除非它是一个集合,因此EF通过保持不变的主键知道行

当EF生成模型时,它包含关于数据库中主键是哪个列的信息
db.Entry(model)
使用该主键将模型绑定到上下文,当调用
SaveChanges()
时,它在数据库中共享的任何主键都将被模型中的数据覆盖。如果主键为0或为空,则必须将
状态设置为
EntityState。添加了
,而不是
EntityState.Modified

正如另一个答案所说,这可能会失败。绑定失败的原因是上下文只能跟踪单个不同的实体一次(实体是不同的类和id)。如果您尝试执行以下操作,将出现异常:

var dbModel = db.Movie.Find(movie.ID);
db.Entry(movie.ID) // Doesn't matter what you do, this will always fail 
因为db上下文已经在跟踪具有相同ID的
电影


这是您不希望在用户之间共享db上下文的一个更大的原因,因为另一个用户尝试更新相同的条目将导致第二个用户抛出异常。虽然事务将是ACID,但最终用户之间可能会出现边缘案例竞争条件(因为没有更好的术语)。

这只是另一种可能的方式。对我来说,当我试图解决类似的问题时,
db.Entry
的版本不起作用。我把我的评论放在这里,而不是作为答案,因为我不确定我是否能完全解决你的问题。你在帖子中问“如果所有属性……都改变了,如何确定哪一行”。要记住的重要一点是,对象的主键永远不会更改,因此确定正确的行很容易。(当密钥可以更改时,可能存在有效的用例…但这非常非常罕见。)感谢您的回答Jason,是的,您的回答绝对正确,但我遇到此类问题的原因是我不知道我不应该/不能更改EF中的主键:)现在我知道这对我来说非常清楚,无论如何,谢谢您的回答,干杯!:)不更改PK并不严格限于EF…这适用于存储数据的任何地方(SQL、Oracle、XML文件、csv文件等)。如果您创建了对象(或实体等)并且它被赋予了一个唯一的标识符,那么这个标识符应该是永久的。谢谢你的精彩解释!@csharpnearchiner Related如果你想看到一种方法来压缩EF的性能,请查看这个关于如何在控制器之间为同一请求共享上下文的文章:(完全公开,这也是我)。您不能更改主键(ID)。