我正在 Sharp 架构中使用 Wcf。我已经使用 WcfSessionStorage 等按照 Northwind 示例配置了我的项目。我在 wcf 服务中有一个方法,可以使用 Repository<>.GetAll() 获取业务对象列表。我正在使用 WcfTestClient 测试服务方法。当第一次调用该方法时,一切正常。但是,在后续调用中,我在 Repository<>.GetAll() 方法上收到以下异常
[System.ObjectDisposedException]
Session is closed!
Object name: 'ISession'
似乎 NHibernate session 在每次调用后都会被释放。我通过使用以下属性装饰我的服务解决了这个问题
[ServiceBehavior( InstanceContextMode = InstanceContextMode.PerCall )]
public class WcfService : IWcfService
{
}
然而,这意味着,每次调用都会创建一个服务实例,进而创建一个新的 nhibernate session 等。在我的场景中,不需要每次调用创建一个新的服务实例,我认为这是一个昂贵的过程过程而不是正确的解决方案。我想知道我的场景中的最佳实践是什么,以及如何通过每次调用创建一个新的服务实例来实现此功能。
谢谢 纳比尔
最佳答案
最简单的方法是每次创建一个新实例,这不是一个昂贵的过程,因为在 .NET 中创建一个新对象大约需要 0.00000000000000001 秒(我在 Ayande 的博客或其他地方读到)。
我在项目中使用 Autofac DI,并且通常将 ISession 作为容器范围(每个请求一个)。然后,每个(直接或间接)使用 ISession 的类都必须是容器范围或更低(工厂范围==每个类使用都会得到一个新实例)。如果使用 ISession 的类具有更高的作用域( session 作用域 == 单例),您将遇到当前遇到的问题。
如果你的服务是单例服务: 第一次运行时会创建服务,该服务使用 ISession,它应该是容器范围的,并且是在第一次运行时。 对服务的下一个请求(服务现已创建)仍然具有对创建的 ISession 的引用(在上一个结束请求时已关闭),因此现在它已关闭。
我不建议使用您将打开/关闭的相同 ISession(NHibernate 文档中不推荐),只需使用容器范围(我这样做并且没有任何性能问题),或者您应该在服务中的每个方法中手动创建 ISession,例如:
using(ISession s = ISessionFactory.OpenSession())
using(ITransaction t = .....)
....
但这一点都不好......
关于wcf - NHibernate Session 在每次 wcf 服务方法调用时被释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3193251/