我已经使用
Spring.NET和NHibernate多年了,我非常满意.但是,我总是在玩多线程,Reactive Extensions以及最终的Task Parallel Library这是一个很棒的框架.不幸的是,由于NHiberntate的会话不是线程安全的,所有类型的多线程方法都会失败.
我问你如何从并行编程中受益并仍然使用NHibernate.
例如:我有一个CustomerRegistrationService类,该方法Register执行多个任务:
ICustumer customer = this.CreateCustomerAndAdresses(params); this.CreateMembership(customer); this.CreateGeoLookups(customer.Address); this.SendWelcomeMail(customer);
最后两种方法是并行运行的理想候选者,CreateGeoLookups调用一些Web服务来确定客户地址的地理位置,并创建一些新实体以及更新客户本身. SendWelcomMail按照它说的做.
因为CreateGeoLookups确实使用了NHibernate(虽然通过存储库对象,因此NHibernate通过接口/依赖关系实际上被隐藏),但它不能与Task.Factory.StarNew(…)或其他线程机制一起使用.
我的问题不是解决我所描述的这个问题,但我想听听你关于NHibenrate,Spring.NET和并行方法的问题.
非常感谢你
马克斯
解决方法
在NH中它的ISession不是线程安全的,但ISessionFactory完全是线程安全的,很容易支持你所看到的.如果您已经设计了会话生命周期管理(以及依赖它的存储库),这样您就可以假设一个单一的ISession跨越调用,那么,是的,您将遇到这种麻烦.但是,如果您将会话处理模式设计为仅假设单个ISessionFactory而不是对ISession进行假设,则没有任何内在阻止您与NH并行进行交互.
虽然您没有特别提到您的用例是用于Web,但重要的是要注意以Web为中心的用例(例如,Spring.NET用户以及许多其他NH的常见情况是什么)管理框架),经常使用的“会话每请求”模式的ISession管理(在Spring.NET中通常称为“在视图中打开会话”或只是“OSIV”)将不起作用,您将需要切换到您的ISession生命周期的不同持续时间.这是因为(顾名思义)每个请求/ OSIV模式会使(在你的情况下现在不正确)假设在每个HttpRequest的持续时间内只有一个ISession实例(并且可能你想要成为产生这些并行NH调用都在Web用例中的单个HttpRequest的上下文中.
显然,在非Web情况下,每个请求的会话很少有类似的概念,因此会话生命周期管理很少像在Web中那样细粒度/短期存在,因此不太可能遇到此问题.基于应用程序.
希望这可以帮助.
-Steve B.