使用 DefaultCascade.All() 将实体添加到列表时,Nhibernate 不会设置 Id
使用 ASP.net MVC,我正在这样做:
[HttpPost]
[TransactionFilter]
public ActionResult Create(User user)
{
// Ommited some things for the sake of brevity
_userRepository.Add(user);
return RedirectToAction("Details", new { Id = user.Id });
}
这按我的预期工作。现在我尝试这样做:
[HttpPost]
[TransactionFilter]
public ActionResult Create(User user, ChildOfUser userChild)
{
// Ommited some things for the sake of brevity
var parent = _userRepository.GetById(user.Id);
parent.Children.Add(userChild);
return RedirectToAction("Details", new { Id = userChild.Id });
}
这失败了,因为 userChild.Id 为空。第一种情况有效,因为在存储库中我调用 session.Save(user);
,并且此调用将更改 user.Id 属性。
(User)parent.Children.Add(userChild);
调用不会更改 userChild.Id 属性。只有在调用 transaction.Commit();
之后,userChild.Id 才会具有有意义的值。虽然我希望通过将 userChild 添加到集合中来设置 Id。
现在,NHibernate 应该处理这个问题吗?还是我的期望是错误的?如果有一种方法让 NHibernate 处理这个问题那就太棒了。
编辑 在这种情况下,ID 始终是 GUID。我可以自己设置它们吗(它们是全局唯一的……),NHibernate 会像它自己生成 Id 一样使用它们吗?
With ASP.net MVC I'm doing this:
[HttpPost]
[TransactionFilter]
public ActionResult Create(User user)
{
// Ommited some things for the sake of brevity
_userRepository.Add(user);
return RedirectToAction("Details", new { Id = user.Id });
}
This works as I expected. Now I'm trying to do this:
[HttpPost]
[TransactionFilter]
public ActionResult Create(User user, ChildOfUser userChild)
{
// Ommited some things for the sake of brevity
var parent = _userRepository.GetById(user.Id);
parent.Children.Add(userChild);
return RedirectToAction("Details", new { Id = userChild.Id });
}
This fails because userChild.Id is null. The first case works because in the repo I call session.Save(user);
, and this call will change the user.Id property.
The (User)parent.Children.Add(userChild);
call won't change the userChild.Id property. Only after calling transaction.Commit();
the userChild.Id will have a meaningfull value. While I expect that the Id would be set by adding the userChild to the collection.
Now, should NHibernate handle this? Or are my expectations wrong? If there's a way to let NHibernate handle this that would be awesome.
EDIT
The Id's in this case are always GUID's. Can I set them myself (they are Globally unique right...), and will NHibernate use that as if it generated the Id itself?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
parent.Children.Add(userChild);
与 NHibernate 无关,它们是内存中操作,实际上它们是 .NET 基础库的一部分,很久以前就有人将 Hibernate 移植到 .网。 collection.Add 不是 NHibernate 操作您观察到的是正确的,NHibernate 对您的对象的作用只有在您调用 Save/Commit 时才会发挥作用。
The
parent.Children.Add(userChild);
has no bearing on NHibernate, they are in-memory operations, in fact they are part of base libraries of .NET, long time before someone ported Hibernate to .NET. collection.Add is not an NHibernate operationWhat you observed is correct, NHibernate's role on your objects will come into play only when you call the Save/Commit.
不,这是由于工作单元模式造成的。工作单元模式背后的一条推理是实用的,它涉及减少事务和数据库往返次数。采用工作单元模式的另一个原因是它与业务意义上的工作单元保持一致——工作单元定义了业务领域中操作的边界。由于 NHibernate 不知道业务域的性质,工作单元的声明被委托给客户端。此外,将工作单元声明委托到持久层之外通常是有利的。有关示例,请参阅此问题。
No and this is due to the Unit of Work pattern. One line of reasoning behind the unit of work pattern is practical and is concerned with reducing the number of transactions and round trips to the database. Another reason for employing the unit of work pattern is that it aligns with a unit of work in a business sense - a unit of work defines the boundaries of an operation in the business domain. Since NHibernate does not know the nature of the business domain the declaration of the unit of work is delegated to the client. Furthermore, it is often advantageous to delegate the unit of work declaration outside of your persistence layer. See this question for examples.
我在使用 .Add() 之后通过使用 ISession.Flush() 方法解决了这个特殊问题,
但我不推荐这种做法。现在,我立即在实体构造函数中设置 Guid Id。这让 MVC 和 NHibernate 都很高兴。
I've had this particular problem solved by using the ISession.Flush() method after using .Add()
I wouldn't recommend this practise though. Nowadays I set the Guid Id immediately in the entities constructor. This makes both MVC and NHibernate happy.