我是NHibernate的新手,在过早关闭会话时遇到了一些问题。我通过重用会话而不是每个事务打开一个会话来暂时解决了这个问题。但是,我的印象是,每次需要时打开会话都是会话生命周期管理的推荐方法。没有?
因此;推荐的会话方式是什么?他们的一生应该是什么?一次会议交易?一个单一的会议来处理一切?或者是什么?
修改
请注意,我的应用程序架构是与服务器端服务通信的桌面应用程序,这是使用NHibernate + Fluent进行所有数据库处理的内容。 (如果这有任何区别......)
答案 0 :(得分:26)
您需要一个会话管理策略,允许您的应用程序有效运行并利用NHibernate为您提供的功能 - 最明显的是缓存和延迟加载。
创建会话是一个廉价的过程,需要很少的前期RAM或CPU,因此您不必担心保存或重新使用会话(实际上,重新使用它们会导致一些令人讨厌和不期待的方面 - 效果)。会话工厂是昂贵的东西,应该只在应用程序启动时构建一次。
经验法则是:会话生命周期需要足够长,以至于在会话结束后您没有持久化对象在范围内。
会话结束后,您从该会话获得的对象的所有更改跟踪都会停止,因此除非您故意将该对象重新附加到新会话,否则这些更改不会保存。因此,只要您从中获取的对象存在,该会话就应该存在。在Web应用程序中,这通常表示每个请求的会话;在WinForms中,每个表单的会话。
在您的情况下,使用服务(我假设它正在运行作为 Windows服务)执行NHibernate工作时,您可能希望考虑为来自使用桌面应用的每个新请求创建会话,并在服务请求时处理它。不确切知道你的服务是如何运行的以及桌面应用程序用来与它交谈的机制(远程处理?WCF?普通的旧SOAP?)我真的不能更具体。
(这个一般规则有一些例外 - 假设你有一组持久化对象代表一个共享资源,其他代码将引用但不会改变,你可以在app-start时预先加载它们并保留它们从那时开始断开连接。)
如果你发现在这样的策略下表现迟缓,那么你可能只是过多地与数据库交谈而且你的对象图很复杂;在这种情况下,请查看second-level caching。
答案 1 :(得分:11)
在网络应用中,每个请求应该有一个会话。这使您可以完全控制会话生命周期并简化错误处理。
在桌面应用中,我建议每个演示者使用一个会话(如果您愿意,可以使用表单)。引用Ayende的MSDN Magazine article:
桌面推荐的做法 应用程序是使用每个会话 形式,使每个形式在 应用程序有自己的会话。每 形式通常代表一种截然不同 用户想要的工作 执行,所以匹配会话 终生到形式的一生有效 在实践中相当不错。补充说 好处是你不再拥有 内存泄漏的问题,因为 当你关闭表格时 申请,你也处理 会话。这将使所有的 由...加载的实体 有资格进行填海的会议 垃圾收集器(GC)。
还有其他原因 更喜欢每个表单一个会话。 你可以利用NHibernate的优势 改变跟踪,所以它将冲洗所有 你改变数据库 提交交易。它也是 在两者之间创造隔离屏障 不同的形式,所以你可以提交 没有的更改为单个实体 担心其他人的变化 在其他上显示的实体 形式。
答案 2 :(得分:6)
会话应对应于工作单元。当您使用该会话检索或持久保存的对象时,会话应保持活动状态。
答案 3 :(得分:2)
没有一个适合所有情况的答案。 Summer of Nhibernate的第13节概述了这个问题。
答案 4 :(得分:0)
大部分NHibernate框架和Microsoft ADO.NET实体框架都很相似。这是一篇关于如何在ADO.NET EF中控制ObjectContext生命线的非常好的文章。
它也应该适用于NHibernate会话。