NHibernate会话(和无状态会话)和长时间运行的应用程序



在旨在运行作业的windows web服务的上下文中,我们尝试重用我们为web应用程序开发的NHibernate DAL。

对于会话管理,我们有两种选择,每种选择都有其优点和缺点:

有状态会话

  • 随着它跟踪所有内容(L1/会话缓存),它将增长很多
  • 需要小心关闭,会话处理似乎不足以清除一级缓存(我注意到使用内存探查器)

无状态会话

  • 当前无法重用映射。所有用"lazy=true"声明的包最终都会出现以下异常(即使会话尚未关闭):

初始化[…]无法延迟初始化角色集合:[…],没有会话或会话关闭

显然,我们不能用lazy="false"来更新映射(它们与web应用程序共享),这将是性能的一个巨大缺点

  • 无法与二级缓存交互:当部署共享二级缓存时,服务将无法使二级缓存数据无效,以便web应用程序拥有最新的数据

NHibernate已经被证明是很好的,直到现在,我们已经成功地在web上下文中使用了有状态会话和NHibernateLINQ,并使用了用于依赖注入的结构图。

我的问题是:

  • 有什么好的解决方案可以在长时间运行的线程中使用NHibernate吗
  • 我更喜欢使用有状态会话,但如何避免内存泄漏

问题解决了!实际上有几个问题。

第一个是关于实例的范围和多线程:

  • 为每个线程创建一个新会话
  • 线程完成工作后,立即清理所有附加到线程的实例。使用StructureMap,在线程中使用new HybridLifecycle().FindCache().DisposeAndClear();。它将导致连接到线程的会话关闭并进行处理
  • 当生命周期是线程范围的时,StructureMap使用ThreadStatic变量来保持对对象缓存的引用。因此,诀窍是在线程中调用StructureMap的ObjectFactory。最初,在我们的应用程序中,一个主线程负责创建新线程,并调用ObjectFactory。这是我们犯的主要错误,而且一旦他们的工作完成,我们确实无法清理线程

会话类型:

  • 只要小心地处理了实例化的StateFul会话,就不需要使用StateLessSession。在我们的案例中,StatelessSession有太多的缺点(缓存管理是主要的)

重要提示:请注意仅实例化一次NHibernate NHibernat会话工厂!

当仔细管理NHibernate实例时,不会出现内存泄漏。

在长时间运行的进程中保持有状态会话打开从来都不是一个好主意。

我的建议是重新设计您的流程,将与数据库相关的代码与非数据库相关的编码分离开来,这样任何与数据库有关的操作都可以在短时间内进行。

最新更新