4

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

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

有状态的会话

  • 因为它会跟踪所有内容(L1/会话缓存),所以会增长很多
  • 需要小心关闭,会话处理似乎不足以清除 L1 缓存(我使用内存分析器注意到的)

无状态会话

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

Initializing [...] failed to lazyly initialize a collection of role: [...], no session or session was closed

显然,我们不能使用lazy="false" 更新映射(它们与网络应用程序共享),这将是性能的巨大缺陷

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

到目前为止,NHibernate 已经被证明是好的,我们已经成功地在 web 上下文中使用了有状态会话和 NHibernate LINQ,以及用于依赖注入的结构图。

我的问题是:

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

2 回答 2

2

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

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

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

会话类型:

  • 无需使用 StateLessSession,只要实例化的 StateFul 会话被仔细处理。在我们的例子中,StatelessSession 有太多的缺点(缓存管理是主要的)

重要提示:注意只实例化 NHibernate NHibernate Session Factory 一次!

当 NHibernate 实例被仔细管理时,没有内存泄漏。

于 2012-10-18T07:07:45.190 回答
0

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

我的建议是重新设计您的流程,将数据库相关代码与非数据库相关代码分开,这样任何与数据库相关的操作都可以保留在一个短跨度会话中。

于 2012-10-10T20:22:52.433 回答