Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 优化:使用PerSession InstanceContext实现WCF的Castle ActiveRecord会话范围_C#_Wcf_Nhibernate_Castle Activerecord - Fatal编程技术网

C# 优化:使用PerSession InstanceContext实现WCF的Castle ActiveRecord会话范围

C# 优化:使用PerSession InstanceContext实现WCF的Castle ActiveRecord会话范围,c#,wcf,nhibernate,castle-activerecord,C#,Wcf,Nhibernate,Castle Activerecord,为了方便在使用AR的WCF服务上进行延迟加载,我为WCF创建了一个会话范围PerRequest解决方案 如果您想在网站或web服务中使用ActiveRecord,您必须通过它在web环境中运行的配置告诉它 无论它如何假设它将具有WCF中不存在的HttpContext.Current 因此,我们告诉AR使用我们自己的AbstractThreadScopeInfo实现,它也实现了IWebThreadScopeInfo,告诉AR它与每个请求的会话模式兼容,该模式现在变成了每个会话的会话模式 为我从中遇

为了方便在使用AR的WCF服务上进行延迟加载,我为WCF创建了一个会话范围PerRequest解决方案

如果您想在网站或web服务中使用ActiveRecord,您必须通过它在web环境中运行的配置告诉它

无论它如何假设它将具有WCF中不存在的HttpContext.Current

因此,我们告诉AR使用我们自己的AbstractThreadScopeInfo实现,它也实现了IWebThreadScopeInfo,告诉AR它与每个请求的会话模式兼容,该模式现在变成了每个会话的会话模式

为我从中遇到的延迟加载异常添加了一些修复

如上所示,我们需要一个WCFStackContainer,它可以添加到当前的OperationContext.Extensions中。为了促进这一点,需要实现IExtension。请看这里:

public class WCFStackContainer : IExtension<OperationContext>
{
    private Stack _stack;

    public Stack Stack 
    {
        get { return _stack; }
        set { _stack = value; }
    }

    #region Implementation of IExtension<OperationContext>

    public void Attach (OperationContext owner)
    {
        //On Attachment to the OperationContext create a new stack.
        _stack = new Stack();
    }

    public void Detach (OperationContext owner)
    {
        _stack = null;
    }

    #endregion
}
这无法在WCF中完成,因此您需要以下内容:

public class ARSessionWCFExtension : IExtension<OperationContext> 
{
    private static readonly ILog Logger = LogManager.GetLogger (typeof(ARSessionWCFExtention));
    private SessionScope _session;

    #region IExtension<OperationContext> Members

    public void Attach (OperationContext owner)
    {
        Logger.Debug ("Attachig ARSessionScope to WCFSession");
        _session = new SessionScope();
    }

    public void Detach (OperationContext owner)
    {
        try
        {
            Logger.Debug ("Detaching ARSessionScope from WCFSession");
            if (_session != null)
                _session.Dispose ();
        }
        catch(Exception ex)
        {
            Logger.Fatal ("Exception: " + ex.Message + " Stacktrace: " + ex.StackTrace);
        }
    }

    #endregion
}
在IDisposable实现中,我们添加了这个。我们很高兴:

    public void Dispose()
    {
        try 
        {
            foreach (var extension in OperationContext.Current.Extensions.Where (ex => ex is ARSessionWCFExtention).ToList ())
                OperationContext.Current.Extensions.Remove (extension);

            Logger.Debug ("Session disposed ClinicID: " + _currentClinic.ClinicID);
        } 
        catch (Exception ex)
        {
            Logger.Fatal ("Exception message: " + ex.Message + " StackTrace: " + ex.StackTrace);
        }
    }
但它不起作用OperationContext.Current为null!。在对MSDN进行了数小时毫无意义的搜索后,我发现没有OperationContext,因为OperationContext只有在客户端启动代码时才可用

我现在已经解决了这个问题,将当前的OperationContext和SessionID存储在构造函数中,并在Deconstructor中比较它们,然后使用它们来处理会话

因此,我现在有:

.ctor
{
    _current = OperationContext.Current;
    _sessionID = OperationContext.Current.SessionId;

    OperationContext.Current.Extensions.Add (new ARSessionWCFExtention ());
}

public void Dispose()
{
    try 
    {
        OperationContext.Current = _current;
        if (OperationContext.Current.SessionId != _sessionID)
            throw new Exception("v weird!");

        foreach (var extension in OperationContext.Current.Extensions.Where (ex => ex is ARSessionWCFExtention).ToList ())
            OperationContext.Current.Extensions.Remove (extension);

        Logger.Debug ("Session disposed ClinicID: " + _currentClinic.ClinicID);
    } 
    catch (Exception ex)
    {
        Logger.Fatal ("Exception message: " + ex.Message + " StackTrace: " + ex.StackTrace);
    }
}
有人知道我怎样才能解决这个问题吗


我尝试处理OperationContext.Channel.Close事件,但这不仅仅在客户端触发。事件OperationContext.OperationComplete fire在每次完成调用后发出。这不是我们想要的,我们希望AR会话持续WCF会话的长度。

你看到了吗?我读过,但我放弃了它,因为它是关于Ayende UnitOfWork实现的,它使用Castle微内核和Windsor,而我没有。但是现在阅读它,制作一个IContractBehavior/IENDPointBehavior实现可能会很酷,它可以实现。它可能会工作,我会研究一下:好的,我尝试过IServiceBehaviour,但只有在配置服务时才会调用它。所以并不是每一个例子都是这样的:S.IContractBehavior是下一个,这里并没有关于Ayende的工作单元的内容。它确实使用温莎的WCF设施,我建议你也使用它,它会让事情变得更简单。正如我之前所说,我不使用温莎。如果我想使用温莎的WCF设施,我相信我必须重新布线和重写大部分服务实现和DL交互。我们在产品开发方面做得太远了,无法开始进行这种根本性的改变。我发现,如果我将自己的IIntanceProvider实现与IContractBehavior相结合,我应该能够在没有Windsor的情况下实现WCF会话到SessionScope实现:你看到了吗?我读过它,但我放弃了它,因为它是关于Ayende UnitOfWork实现的,它使用Castle微内核和Windsor,而我没有。但是现在阅读它,制作一个IContractBehavior/IENDPointBehavior实现可能会很酷,它可以实现。它可能会工作,我会研究一下:好的,我尝试过IServiceBehaviour,但只有在配置服务时才会调用它。所以并不是每一个例子都是这样的:S.IContractBehavior是下一个,这里并没有关于Ayende的工作单元的内容。它确实使用温莎的WCF设施,我建议你也使用它,它会让事情变得更简单。正如我之前所说,我不使用温莎。如果我想使用温莎的WCF设施,我相信我必须重新布线和重写大部分服务实现和DL交互。我们在产品开发方面做得太远了,无法开始进行这种根本性的改变。我发现,如果我将自己的IIntanceProvider实现与iContractBehavior相结合,我应该能够在没有Windsor的情况下进行WCF会话到SessionScope实现:
.ctor
{
    OperationContext.Current.Extensions.Add(new ARSessionWCFExtension());
}
    public void Dispose()
    {
        try 
        {
            foreach (var extension in OperationContext.Current.Extensions.Where (ex => ex is ARSessionWCFExtention).ToList ())
                OperationContext.Current.Extensions.Remove (extension);

            Logger.Debug ("Session disposed ClinicID: " + _currentClinic.ClinicID);
        } 
        catch (Exception ex)
        {
            Logger.Fatal ("Exception message: " + ex.Message + " StackTrace: " + ex.StackTrace);
        }
    }
.ctor
{
    _current = OperationContext.Current;
    _sessionID = OperationContext.Current.SessionId;

    OperationContext.Current.Extensions.Add (new ARSessionWCFExtention ());
}

public void Dispose()
{
    try 
    {
        OperationContext.Current = _current;
        if (OperationContext.Current.SessionId != _sessionID)
            throw new Exception("v weird!");

        foreach (var extension in OperationContext.Current.Extensions.Where (ex => ex is ARSessionWCFExtention).ToList ())
            OperationContext.Current.Extensions.Remove (extension);

        Logger.Debug ("Session disposed ClinicID: " + _currentClinic.ClinicID);
    } 
    catch (Exception ex)
    {
        Logger.Fatal ("Exception message: " + ex.Message + " StackTrace: " + ex.StackTrace);
    }
}