我是否必须在Nhibernate中的SaveOrUpdate之前加载/获取实体?

Lef*_*tyX 7 nhibernate asp.net-mvc viewmodel asp.net-mvc-2 valueinjecter

在我的ASP.NET MVC应用程序中,我将域模型与视图模型分开.
我在viewmodel对象中转换我的实体,这样我就可以只用所需的数据"提供"我的视图(我为此目的使用了valueinjecter).
在保存过程中,我的控制器返回viewmodel对象,将其转换为域模型实体并尝试使用SaveOrUpdate将其保留.我注意到,如果我尝试更新现有记录,Nhibernate会将其视为新对象并强制执行INSERT,即使我的实体具有正确的ID.
我之前没有加载(获取/加载)实体,因为我想避免再次重新映射所有字段.
有什么我做错了吗?实现这一目标的最佳方法是什么?

***** - 更新 - ***

我的控制器收到一个用户(ViewModel),验证它并尝试通过服务层将其保存为实体:

public ActionResult Edit(Guid id, Models.User User)
{
...
var user = new Domain.User();
user.InjectFrom(User);
user.SetId(id);

user = this._SecurityService.SaveUser(user);

}
Run Code Online (Sandbox Code Playgroud)

这是服务:

public Domain.User SaveUser(Domain.User User)
        {
            bool Result = false;

            if (this._ValidationEngine.IsValid(User))
            {
                using (_UnitOfWork)
                {
                    if (User.Code != Guid.Empty)
                    {
                        var user = this._UserRepository.Load(User.Code);
                        user.InjectFrom(User);
                        User = this._UserRepository.Update(user);
                    }
                    else {
                        User = this._UserRepository.Save(User);
                    }
                    Result = _UnitOfWork.Commit();
                }
            }
            return (User);
        }
Run Code Online (Sandbox Code Playgroud)

我很担心我必须多次转换我的viewmodel/entity.现在,当我尝试保存一个新用户时,我收到了这条消息:行被另一个事务更新或删除(或者未保存的值映射不正确)
可能这在某些方面与Darin告诉我的有关.
有没有更好的方法来做我想做的事情?

UPDATE

我注意到错误"Row已更新或删除..."是由于我为我的映射定义了一个版本.我能理解的是我需要将Id版本匹配我想要更新的实体.
我想了解其他人如何用DDD + ASP.NET MVC + NHibernate做这些事情?

我的所有实体都定义了一个版本(我忘了说,对不起):

<version name="Version" type="System.Int32" unsaved-value="0">
   <column name="Version" not-null="true" />
</version>
Run Code Online (Sandbox Code Playgroud)

正如Ayende 在这里解释的那样,Nhibernate试图用这样的查询来更新我的实体:

UPDATE Table SET field1 = 'bla', Version = (y+1) WHERE id = x AND Version = y
Run Code Online (Sandbox Code Playgroud)

其中y应该是我的实体的版本.由于我没有使用版本填充我的实体,因此会生成异常StaleObjectException.
我在我的viewmodel中添加了一个版本字段.我将它与id一起保存在我视图的隐藏区域中.
我的控制器现在收到一个带有Id和版本的viewmodel.我在我的域实体中注入这些字段并让存储库保存它(我不重新加载我的实体):

User = this._UserRepository.Update(user);
Run Code Online (Sandbox Code Playgroud)

如果我收到StaleObjectException异常,则表示其他人已更新数据库行,我将向用户提供一些反馈.

Die*_*hon 0

由于您已经有了一个 ID,因此知道这是一个更新,因此请使用session.Update代替SaveOrUpdate