42

我是 NHibernate 的新手,过早关闭会话时遇到了一些问题。我通过重用会话而不是为每个事务打开一个会话来暂时解决了这个问题。但是,我的印象是,每次需要时打开会话是会话生命周期管理的推荐方法。不?

所以; 处理会话的推荐方式是什么?他们的一生应该是怎样的?一个会话 pr 交易?一个单例会话来处理所有事情?要不然是啥?

编辑:

请注意,我的应用程序架构是与服务器端服务通信的桌面应用程序,这是使用 NHibernate + Fluent 处理所有数据库的内容。(如果这有什么不同......)

4

5 回答 5

27

您需要一个会话管理策略,让您的应用程序有效地运行并利用 NHibernate 为您提供的东西 - 最值得注意的是缓存和延迟加载。

创建会话是一个成本低廉的过程,并且需要很少的前期 RAM 或 CPU,因此您不必担心保存或重复使用会话(实际上,重复使用它们会导致一些令人讨厌的和未预料到的副作用)。会话工厂是昂贵的东西,应该在应用程序启动时构建一次且仅一次。

经验法则是这样的:会话生命周期需要足够长,以至于会话结束后您没有持久的对象在范围内徘徊。

会话结束后,您从该会话获得的对象的所有更改跟踪都会停止,因此除非您故意将该对象重新附加到新会话,否则不会保存这些更改。因此,只要您从中获取的对象存在,该会话就应该存在。在 Web 应用程序中,这通常意味着每个请求都有一个会话;在 WinForms 中,每个表单都有一个会话。

在您的情况下,使用服务(我假设它作为Windows 服务运行)执行 NHibernate 工作,您可能希望考虑为来自消费桌面应用程序的每个新请求创建一个会话,并在该请求得到服务时处理它. 不知道您的服务是如何运行的,以及桌面应用程序使用什么机制与之交谈(远程处理?WCF?普通的旧 SOAP?)我真的不能更具体。

(此一般规则有一些例外情况 - 假设您有一组持久对象,它们表示其他代码将引用但不会更改的共享资源,您可以在应用程序启动时预先加载这些对象,然后让它们断开连接在。)

如果您发现在这种策略下性能低下,可能是您与数据库的对话过多并且您的对象图很复杂;在这种情况下查看二级缓存。

于 2010-01-06T15:00:53.220 回答
11

在 Web 应用程序中,每个请求应该有一个会话。这使您可以完全控制会话生命周期并简化错误处理。

在桌面应用程序中,我建议为每个演示者使用一个会话(或者如果您愿意,可以使用表单)。在他的MSDN 杂志文章中引用 Ayende 的话:

桌面应用程序的推荐做法是为每个表单使用一个会话,以便应用程序中的每个表单都有自己的会话。每个表单通常代表用户想要执行的一项不同的工作,因此将会话生命周期与表单生命周期相匹配在实践中非常有效。额外的好处是您不再有内存泄漏的问题,因为当您关闭应用程序中的表单时,您也会处理会话。这将使会话加载的所有实体都符合垃圾收集器 (GC) 的回收条件。

每个表单选择一个会话还有其他原因。您可以利用 NHibernate 的更改跟踪,因此它会在您提交事务时将所有更改刷新到数据库。它还在不同表单之间创建了隔离屏障,因此您可以将更改提交到单个实体,而不必担心对其他表单上显示的其他实体的更改。

于 2010-01-06T14:23:55.230 回答
6

一个会话应该对应一个工作单元。当您处理使用该会话检索或保留的对象时,该会话应该保持活动状态。

于 2010-01-06T14:20:15.110 回答
2

没有适合所有情况的答案。Summer of Nhibernate的第 13 节很好地概述了这个问题。

于 2010-01-06T14:21:47.450 回答
0

许多 NHibernate 框架和 Microsoft ADO.NET 实体框架是相似的。这是一篇关于如何在 ADO.NET EF 中控制 ObjectContext 生命线的非常好的文章。

http://blogs.msdn.com/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx

它也应该适用于 NHibernate 会话。

于 2010-01-06T14:22:13.623 回答