NHibernate 会话的生命周期应该是多长?
我是 NHibernate 的新手,在过早关闭会话时遇到了一些问题。我通过重用会话而不是为每个事务打开一个会话来暂时解决了这个问题。然而,我的印象是,每次需要时打开会话是会话生命周期管理的推荐方法。不?
所以;处理会话的推荐方法是什么?他们的一生应该是怎样的?一次交易?一个单例会话可以处理所有事情?或者什么?
编辑:
请注意,我的应用程序架构是一个与服务器端服务通信的桌面应用程序,这是使用 NHibernate + Fluent 进行所有数据库处理的内容。 (如果这有什么区别的话......)
I'm new to NHibernate, and have seen some issues when closing sessions prematurely. I've solved this temporarily by reusing sessions instead of opening a session per transaction. However, I was under the impression that opening sessions each time you need them was the recommended approach for session lifetime management. No?
So; what is the recommended way of handling sessions? What should their lifetime be? One session pr transaction? One singleton session to handle everything? Or what?
Edit:
Note that my application architecture is a desktop application communicating with a server side service, which is what does all the Database handling, using NHibernate + Fluent. (If this makes any difference...)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要一个会话管理策略,使您的应用程序能够有效运行并利用 NHibernate 为您提供的功能 - 最显着的是缓存和延迟加载。
创建会话是一个成本低廉的过程,并且只需要很少的前期 RAM 或 CPU,因此您不必担心保存或重复使用会话(事实上,重复使用它们可能会导致一些令人讨厌和无法预料的副作用)。会话工厂是昂贵的东西,应该在应用程序启动时构建一次且仅一次。
经验法则是:会话生存期需要足够长,以便会话结束后不会有持久对象在范围内徘徊。
会话结束后,从该会话获得的对象的所有更改跟踪都会停止,因此除非您故意将该对象重新附加到新会话,否则这些更改不会保存。因此,只要您从中获取的对象存在,会话就应该存在。在 Web 应用程序中,这通常意味着每个请求都有一个会话;在 WinForms 中,每个表单都有一个会话。
在您的情况下,通过一个服务(我假设它作为 Windows 服务运行)执行 NHibernate 工作,您可能希望考虑为来自消费桌面应用程序的每个新请求创建一个会话,并处理当该请求得到满足时。不确切地知道您的服务如何运行以及桌面应用程序使用什么机制与之通信(远程处理?WCF?普通的旧式 SOAP?)我真的无法更具体。
(这个一般规则有一些例外 - 假设您有一组持久对象,它们代表其他代码将引用但不会更改的共享资源,您可以在应用程序启动时预先加载这些对象,然后让它们断开连接)
如果您发现在这种策略下性能缓慢,则可能是您与数据库的对话过多并且您的对象图很复杂;在这种情况下,请查看二级缓存。
You want a session management strategy that allows your app to function effectively and take advantage of the things that NHibernate gives you - most notably caching and lazy loading.
Creating sessions is an inexpensive process and requires little up-front RAM or CPU, so you shouldn't worry about conserving or re-using sessions (indeed, re-using them can lead to some nasty and un-anticipated side-effects). The session factory is the expensive thing and should be built once and only once at app startup.
The rule of thumb is this: the session lifetime needs to be long enough that you don't have persisted objects hanging around in scope after the session ends.
Once the session ends, all change tracking for objects you got from that session stops, so those changes don't get saved unless you deliberately re-attach that object to a new session. The session should therefore be around for as long as the objects you fetch from it are going to exist. In a Web app, that generally means a session for each request; in WinForms, a session for each form.
In your case, with a service (I assume it's running as a Windows service) doing the NHibernate work, you might wish to consider having a session created for each new request from the consuming desktop app, and disposing it when that request has been serviced. Not knowing exactly how your service runs and what mechanism the desktop app uses to talk to it (remoting? WCF? Plain old SOAP?) I can't really be more specific.
(There are some exceptions to this general rule - suppose you have a set of persisted objects that represent a shared resource to which other code will refer but not change, you can load these up-front at app-start and leave them disconnected from then on.)
If you find performance sluggish under such a strategy, it may be that you're just talking to the database too much and your object graph is complex; look at second-level caching in this case.
在网络应用程序中,每个请求应该有一个会话。这使您可以完全控制会话生命周期并简化错误处理。
在桌面应用程序中,我建议为每个演示者使用一个会话(如果您愿意,也可以使用表单)。引用 Ayende 在他的 MSDN 杂志文章中的话:
In a web app, you should have one session per request. This gives you full control over the session lifetime and simplifies error handling.
In a desktop app, I recommend using a session per presenter (or form if you prefer). To quote Ayende in his MSDN Magazine article:
一个会话应该对应一个工作单元。当您使用该会话检索或保留的对象时,该会话应该保持活动状态。
A session should correspond to a unit of work. The session should stay alive while you are working with the objects retrieved or persisted using that session.
没有一种答案适合所有情况。 Nhibernate 之夏 的第 13 次会议对该问题进行了很好的概述。
There isn't one answer that fits all situations. Session 13 of Summer of Nhibernate presents a nice overview of the issue.
NHibernate 框架和 Microsoft ADO.NET Entity Framework 的大部分内容都是相似的。这是一篇关于如何控制 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< /a>
它也应该适用于 NHibernate 会话。
Much of the NHibernate framework and Microsoft ADO.NET Entity Framework are similar. Here is a very good article about how you should control an ObjectContext lifeline in the ADO.NET EF.
http://blogs.msdn.com/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx
It should apply to NHibernate sessions as well.