WCF / S#arpArch:在请求中的第一次调用之后,底层ISession将关闭

时间:2010-03-04 08:42:41

标签: c# wcf nhibernate s#arp-architecture

我知道在SA中使用WCF已被弃用,因为它将转移到SA Contrib。但在它出现之前,我想我必须使用SA中的支持。

也就是说,我在调用WCF服务后关闭了底层的NHibernate会话。我的存储库的DbContext.Session在第一次调用后关闭,因此在单个HTTP请求期间我不能多次调用我的服务。

我已根据Northwind示例应用程序在我的项目中设置了WCF。该示例仅在每个请求中调用一次WCF服务,因此此问题不会显示在那里。但是,通过复制以下行,可以轻松复制该问题 TerritoriesController:

territories = territoriesWcfService.GetTerritories();

抛出一个ObjectDisposedException:“会话已关闭!对象 名称:'ISession'“。

有什么想法吗?

2 个答案:

答案 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并不熟悉,但看起来你在这里至少有两个选择:

  1. 在客户端,请在之后配置WCF服务 第一次打电话并新建另一个WCF 在做第二次之前的服务 打电话,从而得到一个新的ISession。

  2. 使WCF服务更智能 关于你的会话处理 可以保持会话开放时间更长。 有多种方法可以做到这一点 它可能涉及一个体面的 WCF服务中新逻辑的数量,但它应该 完全可行。