正确处理NHibernate中的瞬态实体

时间:2010-11-06 19:39:54

标签: .net nhibernate transient .net-3.5 .net-4.0

引用已经存在于不同会话中但在会话关闭后内存中保持不变的实体的正确方法是什么?

一旦NH在单个会话中持续存在并且该会话关闭,我需要在新会话中再次获取它以便在其他一些瞬态实体中引用它。或者,我可以在新会话实例上调用Session.Lock,让NH知道此实体不是瞬态的。在应用生命周期内,此项永远不会更改。

使用的首选方式是什么?还有其他方法吗?

[编辑]

另外一个问题是我使用的是Repository模式,而不是直接在我的业务层使用NH。这意味着我还需要有一种方法来将此调用抽象为Session.Lock,即在我的存储库接口中有一个类似于Session.Lock的方法。这有点臭恕我嘘。

2 个答案:

答案 0 :(得分:3)

最好的方法是启用二级缓存并使该对象符合缓存条件。如果这样做,您可以在存储库方法中获取它,但它将从缓存而不是数据库中获取。

答案 1 :(得分:2)

关于第一个问题。 如果您只是要阅读实体,则无需执行任何操作。即使将其作为字段分配给其他实体也不需要您锁定记录。您需要调用ISession.Lock的唯一原因是您想要变异然后保存实体。

存在异常并且延迟加载。如果实体具有在第一个会话处于活动状态时未加载的外部子记录,则在您稍后尝试访问它们时将引发异常上。最简单的解决方法是在第一次会话中触摸子集。

如果实体在这些情况下仍然给您带来问题,您可以在存储库中添加Load。您可以将其连接到ISession.LoadLoad的作用是为实体创建一个空代理,而不需要访问数据库。此实体是实体加载的会话的一部分,可用于分配给其他实体的属性。这种方法的优点是它更清洁,并且通过单元测试很容易进行模拟。

关于第二个问题。是的,你说的是将ISession.Lock集成到存储库中。同样,当您不必改变实体时,您不必担心这一点。但是,如果你是,那么,你真的应该考虑从存储库中重新加载实体并处理那个实体。我知道它不是最好的,但它可以为你节省很多非常奇怪的代码,特别是在你的单元测试中。

最后一件事。我知道你在谈论一个将存在很长时间的实体(可能是应用程序的完整运行时)。你有大致三种类别的生命:1。永远,2。长和3短。我提到这一点的原因是,不止一次,具有“长”生命周期的实体的问题实际上可以保持与具有相同生命期的会话保持连接。 将会话保持活动状态5分钟或10分钟(用户在表单中输入数据的时间)不是一个问题。仅此一项就可以为大多数人节省很多麻烦。

还有一点需要注意:请查看NHibernateUtilNHibernateProxyHelper。这些类可以帮助您强制加载实体和子集合。