如何在长期使用的Windows窗体应用程序中管理NHibernate会话?

如何在长期使用的Windows窗体应用程序中管理NHibernate会话?,nhibernate,Nhibernate,我们正在使用NHibernate在一个复杂的模块化windows窗体应用程序中管理持久性,但有一个想法一直困扰着我。我们目前在启动时打开一个会话,并通过该会话打开所有对象。我担心所有加载的对象都会被加载到NHibernate会话缓存中,这样它们就不能被垃圾收集,最终我们会把整个数据库都放在内存中 web应用程序永远不会出现这种情况,因为web页面请求(甚至更好的Ajax请求)代表了完美的短期事务,因此可以打开和关闭会话来处理每个请求 但是,如果我在窗体应用程序中加载一个对象树,然后将其放入屏幕上

我们正在使用NHibernate在一个复杂的模块化windows窗体应用程序中管理持久性,但有一个想法一直困扰着我。我们目前在启动时打开一个会话,并通过该会话打开所有对象。我担心所有加载的对象都会被加载到NHibernate会话缓存中,这样它们就不能被垃圾收集,最终我们会把整个数据库都放在内存中

web应用程序永远不会出现这种情况,因为web页面请求(甚至更好的Ajax请求)代表了完美的短期事务,因此可以打开和关闭会话来处理每个请求

但是,如果我在窗体应用程序中加载一个对象树,然后将其放入屏幕上的导航窗格中,它们可能会在应用程序的整个生命周期中保持它们的状态,并且用户可以在任何时候单击它们,导致我们的代码需要将对象关系导航到其他对象(仅在NHibernate会话中有效)


StackOverflow阅读器如何保持NHibernate的优势而不出现我所描述的问题?

我可以看到一些替代方案:

  • 立即加载对象树(从中收集的是默认的)
  • 分离对象,截取“click”事件,然后使用新会话从数据库加载数据。这迫使您自己处理收集,而不是依赖nhibernate,这可能超出了问题的范围(这要求nhibernate的好处,其中之一是收集管理)

  • Ayende和他的公司通常建议每个“对话”使用一个会话。这通常会使会话生命周期持续很短的操作,因此它的行为更像一个web应用程序

    对于树案例,可以使用Bruno的解决方案2。对象可以延迟映射。然后,每次需要访问子集合时,都会启动对话,并通过ISession.Lock重新连接父集合。然后,当数据绑定完成时,关闭该会话。不需要维护太多的开销,只需要几行任何形式的代码就可以进行对话;如果您觉得自己很时髦,您可以扩展表单和正在使用的控件来自动执行此操作


    因此,棘手的部分是来自不同会话的并发编辑。我们不要去那里

    当我需要一个会话时,我会打开它,当我知道我不再需要它时,我会关闭它

    更具体地说,例如,如果我有一个允许我编辑客户信息的表单,我将在表单实例化时打开会话,在表单关闭时关闭会话。
    当我打开该表单的两个实例时,我也打开了两个会话。

    您可以查看我的帖子,了解如何在Windows表单应用程序中使用uNHAddins来处理每个会话(uNHAddins是一个项目,由现任NH负责人Fabio Maulo领导,在NHibernate中添加了一些内容)

    第一个帖子是这个


    从这里,您可以链接到Unaddins trunk。

    这里有一篇文章,介绍了如何在桌面风格的应用程序中实现每个会话的会话: