1

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

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

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

[编辑]

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

4

2 回答 2

3

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

于 2010-11-06T23:45:24.993 回答
2

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

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

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

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

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

另一个注意事项:看看NHibernateUtiland NHibernateProxyHelper。这些类可以帮助您强制加载实体和子集合。

于 2010-11-06T20:08:14.080 回答