C# 从控制器编辑操作更新实体的正确方法?

C# 从控制器编辑操作更新实体的正确方法?,c#,asp.net-mvc,entity-framework,ef-code-first,C#,Asp.net Mvc,Entity Framework,Ef Code First,控制器 首先,我尝试了这个: [HttpPost] public ActionResult Edit(JournalEntry journalentry) { if (ModelState.IsValid) { db.Entry(journalentry).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index", new { id

控制器

首先,我尝试了这个:

[HttpPost]
public ActionResult Edit(JournalEntry journalentry)
{
    if (ModelState.IsValid)
    {
        db.Entry(journalentry).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index", new { id = journalentry.Journal.JournalId });
    }
    return View(journalentry);
}
SaveChanges()
中引发错误:

错误消息:“受影响的存储更新、插入或删除语句” 意外的行数(0)。实体可能已被修改或删除 已删除,因为已加载实体。刷新ObjectStateManager 条目。”

我查看了
journalentry
实体,发现它的JournalEntryId为0,但所有其他属性都设置正确。因此,我将其改为:

[HttpPost]
public ActionResult Edit(int id, JournalEntry journalentry)
{
    if (ModelState.IsValid)
    {
        journalentry.JournalEntryId = id;
        db.Entry(journalentry).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index", new { id = journalentry.Journal.JournalId });
    }
    return View(journalentry);
}

一切看起来都很正常,但这是保存实体的正确方法吗?

实际上,您可以将
JournalEntry
视图模型中的
JournalEntryId
属性重命名为
Id
,然后默认模型绑定器将自动为您填充该属性,这样您就不必编写以下行:

journalentry.JournalEntryId = id;
您的第一个代码段将起作用,因为Id属性将由路由中的值填充

或者,如果由于某种原因,您无法重命名视图模型上的属性(实际上我知道原因=>您根本没有使用任何视图模型,但您将域实体直接传递给视图,这是错误的,但会遇到另一个问题),您可以在表单中使用隐藏字段:

@Html.HiddenFor(model => model.JournalEntryId)
或者修改
Html.BeginForm
声明,将参数作为查询字符串参数包括在内:

@Html.BeginForm("Edit", "SomeController", new { JournalEntryId = Model.JournalEntryId }, FormMethod.Post)
{
    ...        
}

哦,是的,我添加了@Html.HiddenFor(model=>model.JournalEntryId),现在它可以在不传入ID的情况下工作了。传入model有什么问题?所有asp.net/mvc示例项目(如MvcMusicStore)都会直接传入。只有少数情况下它们不在该应用程序中@白ジェームス, 正如我所说的,这取决于另一个问题。但基本上,最好为视图设计特定的类。这些类称为视图模型。它们完全符合给定视图的要求。例如,为了显示某些视图,您可能需要来自不同域模型的信息。因此,您可以构建一个视图模型来聚合这些信息。动作输入参数也是如此=>它们应该始终是视图模型。Dimitov-哦,如果视图需要的信息超过单个模型对象所能提供的,那么这是有意义的。在大多数情况下都是这样。很好的解释。@DarinDimitrov,你说的视图模型是什么意思?我也有同样的问题,你能帮忙吗?从视图中更新实体的正确方法是使用错误的名称,因为您首先不应该这样做。@Dismissible-我更改了标题。现在有意义了吗?同样的道理。你不应该这样做。您应该创建一个视图模型,并将任何数据访问放在服务层中。您永远不应该真正使用数据库实体作为视图的模型。请阅读优秀的MVC/EF教程,该教程展示了正确的方法。请参阅@Rick.Anderson-at-Microsoft.com-OK。那是我还没有经历过的。因为每个人都建议我使用视图模型,我希望这个链接推荐那些。。。