Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 在Nhibernate中保存或更新之前是否必须加载/获取实体?_Asp.net Mvc_Nhibernate_Asp.net Mvc 2_Viewmodel_Valueinjecter - Fatal编程技术网

Asp.net mvc 在Nhibernate中保存或更新之前是否必须加载/获取实体?

Asp.net mvc 在Nhibernate中保存或更新之前是否必须加载/获取实体?,asp.net-mvc,nhibernate,asp.net-mvc-2,viewmodel,valueinjecter,Asp.net Mvc,Nhibernate,Asp.net Mvc 2,Viewmodel,Valueinjecter,在我的ASP.NET MVC应用程序中,我已将域模型与视图模型分离。 我在viewmodel对象中转换实体,以便仅使用所需的数据“馈送”视图(为此我使用ValueInjector)。 在保存过程中,我的控制器将取回viewmodel对象,将其转换为域模型实体,并尝试使用SaveOrUpdate将其持久化。 我注意到,如果我试图更新现有记录,Nhibernate会将其视为新对象并强制插入,即使我的实体具有正确的ID。 我之前没有加载(获取/加载)实体,因为我希望避免再次重新映射所有字段。 我做错什

在我的ASP.NET MVC应用程序中,我已将域模型与视图模型分离。
我在viewmodel对象中转换实体,以便仅使用所需的数据“馈送”视图(为此我使用ValueInjector)。
在保存过程中,我的控制器将取回viewmodel对象,将其转换为域模型实体,并尝试使用SaveOrUpdate将其持久化。 我注意到,如果我试图更新现有记录,Nhibernate会将其视为新对象并强制插入,即使我的实体具有正确的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);

}
这是服务:

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);
        }
我担心我必须多次转换viewmodel/实体。现在,当我尝试保存一个新用户时,我收到一条消息:行被另一个事务更新或删除(或者未保存的值映射不正确)
这可能在某种程度上与达林告诉我的有关。
有没有更好的方法来做我想做的事情

更新

我注意到错误“行已更新或删除…”是因为我为映射定义了一个版本。我能理解的是,我需要让Id版本与我要更新的实体匹配。
我想了解其他人是如何用DDD+ASP.NETMVC+NHibernate做这些事情的

解决方案

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

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


如果我得到一个StaleObjectException异常,这意味着其他人已经更新了DB行,我将向用户提供一些反馈。

要使
保存或更新
按预期工作,您需要在
映射上显式指定
未保存值
属性。例如,你会:

<id unsaved-value="0" ...

由于您已经有了Id,因此知道这是一个更新,请使用
会话。更新
而不是
保存或更新

。如果我的id是Guid类型,我想我必须使用空Guid(00000000-0000-0000-0000-000000000000),对吗?@vandalo,试试这个:
unsaved value=“00000000-0000-0000-0000-000000000000”
(未测试)。再次感谢。不管怎样,你会怎么做?我是否应该从数据库加载实体,并用新实体填充每个字段,以防我尝试更新?有什么最佳实践吗?再次感谢您的帮助。恐怕我不能这样做,因为如果我尝试保存我的实体,我会收到以下消息:具有相同标识符值的另一个对象已与会话关联:caedb8a4-abce-4c6f-b171-9e7200cc7a37,of entity:bprementers.Domain.users,这意味着该对象已加载。那你为什么不更新已经加载的对象呢?对不起,那是个错误。我现在做的是从存储库加载一个实体,并将其与从控制器获得的实体合并。当我尝试插入时,仍然会出现错误“行被另一个事务更新或删除(或未保存的值映射不正确)”。我将用更多信息更新我的原始问题。尝试加载实体,然后重新映射它(我知道你不希望这样),试试这个,告诉我们它是否这样工作。我想我的问题在于版本。我有
UPDATE Table SET field1 = 'bla', Version = (y+1) WHERE id = x AND Version = y
User = this._UserRepository.Update(user);
<id unsaved-value="0" ...