0

为什么我的 ASP.NET MVC3Edit操作被赋予一个新对象而不是要编辑的对象?
当我检查对象的属性时,给定的 ID 值是unsaved-value我在 NHibernate 映射文件中指定的。

为了解决这个问题,我可以从数据库中查询要更新的对象,并从传递给方法的对象中设置我想要的属性。但是,虽然这对于具有一两个属性的非常简单的对象来说是可以的,但当有很多属性并且似乎我正在与系统作斗争时,它很快就会成为一个问题(对我来说,这表明我没有这样做事情按照他们应该做的方式)。

我的映射:

<id name="Id" column="Id" type="Guid" 
    unsaved-value="00000000-0000-0000-0000-000000000000">

我的编辑方法:

[NHibernateActionFilter]
[HttpPost]
public ActionResult Edit(Status status, Guid id)
{
    try
    {
        if (ModelState.IsValid)
        {
            var originalStatus = Session.QueryOver<Status>()
                                        .Where(s => s.Id == id)
                                        .SingleOrDefault<Status>();
            if (originalStatus == null)
                throw new Exception(string.Format("No Status with Id: {0}.", id));

            originalStatus.StatusName = status.StatusName;
            Session.Update(originalStatus );

            return RedirectToAction("Index");
        }
    }
    catch (DataMisalignedException ex)
    {
        // TODO: Log4Net this
        ModelState.AddModelError("", "Unable to save changes. Please try again.");
    }
    return View(status);
}

*这NHibernateActionFilter摘自 Ayende 关于重构无摩擦和无气味代码的一系列帖子,并为控制器中的每个操作提供了一个 ISession。但是,我认为这不是问题的原因。

尝试编辑项目时出现我的问题,StaleObjectException抛出 a:

行被另一个事务更新或删除(或未保存的值映射不正确):[TheWorkshop.Web.Models.Status#00000000-0000-0000-0000-000000000000]

新的 Guid 向我显示提到的状态是新的,而不是先前返回的对象,以便填充详细信息视图。因此,似乎一个新对象已被更新并传递到我的 EditActionResult中,但这没有帮助。

正如我在上面展示的那样,我可以围绕它进行编码,但这更像是一种技巧而不是解决方案。我希望能够像这样离开我的 Edit 方法:

[NHibernateActionFilter]
[HttpPost]
public ActionResult Edit(Status status)
{
    try
    {
        if (ModelState.IsValid)
        {
            Session.Update(status);

            return RedirectToAction("Index");
        }
    }
    catch (DataMisalignedException ex)
    {
        // TODO: Log4Net this
        ModelState.AddModelError("", "Unable to save changes. Please try again.");
    }
    return View(status);
}

编辑
我已经查看了如何处理更新实体的答案。NHibernate + ASP.NET MVC但这几乎完成了我已经完成的工作,我不敢相信更新方法必须像我的尝试那样混乱。

我还查看了这个错误在 nhibernate 中的含义;它看起来与我的问题相同,但我无法得到任何适合我的答案,即问题仍然存在。

4

2 回答 2

3

提供给 action 方法的Status实例是由 MVC 的模型绑定器生成的——它是一个新对象,因为模型绑定器和 NHibernate 彼此一无所知。要使其具有正确的 ID,您需要提供 ID 作为表单的一部分(隐藏)。但请注意,用户不能通过发布比表单包含的字段更多的字段或更改隐藏字段的值来进行未经授权的更改。

有不同的模型是很常见的。MVC 在前端使用视图模型,它们有不同的用途,并且看起来不一定与您的域模型相同。action 方法负责对视图模型中的值进行操作,并对领域模型执行正确的操作。

于 2013-03-04T07:41:17.250 回答
0

我真的无法在 Oskers 答案中添加任何应该标记为正确的内容。只是几点。

在您的原始方法中,由于 Ayende 的属性创建了一个事务,您不需要更新语句,NHibernate 会看到该属性已更改并为您更新它。

如果您觉得第二种方法是可行的方法,您可以通过创建自定义模型绑定器来实现此目的,该绑定器将加载到 Nhibernate 对象中。

见: ASP.NET MVC模型绑定外键关系

于 2013-03-04T20:49:15.100 回答