我知道在SA中使用WCF已被弃用,因为它将转移到SA Contrib。但在它出现之前,我想我必须使用SA中的支持。
也就是说,我在调用WCF服务后关闭了底层的NHibernate会话。我的存储库的DbContext.Session在第一次调用后关闭,因此在单个HTTP请求期间我不能多次调用我的服务。
我已根据Northwind示例应用程序在我的项目中设置了WCF。该示例仅在每个请求中调用一次WCF服务,因此此问题不会显示在那里。但是,通过复制以下行,可以轻松复制该问题 TerritoriesController:
territories = territoriesWcfService.GetTerritories();
抛出一个ObjectDisposedException:“会话已关闭!对象 名称:'ISession'“。
有什么想法吗?
答案 0 :(得分:3)
我设法解决了。
通过检查SharpArch.Wcf源代码,我发现在发送WCF服务响应之前,它总是关闭所有NHibernate会话。这本身就是一件好事。
此外,我发现我的客户端代理工厂每个Web请求只触发一次,而第二个服务调用应该引发一个新的代理实例。结果是第二个服务调用将失败,因为基础NHibernate会话已经关闭。我通过使用 Castle.Core.TransientAttribute 来装饰我的客户端代理类,从而将生命周期管理留给创建客户端的工厂。结果是每次请求代理时都会调用我们的代理工厂。
其次,我必须注册这样的代理(在 ComponentRegistrar 类中):
container.AddFacility("WcfSessionFacility", new WcfSessionFacility());
container.Kernel.AddComponentWithExtendedProperties(
"AccountService",
typeof(IAccountService),
typeof(AccountServiceClient),
new Dictionary<string, object>()
{
{ WcfSessionFacility.ManageWcfSessionsKey, true }
});
WcfSessionFacility 管理客户端的关闭/中止,具体取决于其状态。这样可以确保每当客户端代理被销毁时客户端通道都会关闭,因此我们不需要将我们的调用放在try-catch块中。
和我一样,您可能会考虑在添加组件时配置生命周期管理而不是使用属性,但显然没有合适的 AddComponentWithExtendedProperties 重载允许这样做。
答案 1 :(得分:1)
我对SharpArchitecture并不熟悉,但看起来你在这里至少有两个选择:
在客户端,请在之后配置WCF服务 第一次打电话并新建另一个WCF 在做第二次之前的服务 打电话,从而得到一个新的ISession。
使WCF服务更智能 关于你的会话处理 可以保持会话开放时间更长。 有多种方法可以做到这一点 它可能涉及一个体面的 WCF服务中新逻辑的数量,但它应该 完全可行。