Asp.net mvc 在Nhibernate中保存或更新之前是否必须加载/获取实体?
在我的ASP.NET MVC应用程序中,我已将域模型与视图模型分离。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。 我之前没有加载(获取/加载)实体,因为我希望避免再次重新映射所有字段。 我做错什
我在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" ...