NHibernate + WCF + Windows服务和WcfOperationSessionContext类

Nov*_*ice 7 nhibernate wcf nhibernate-3

  • 我有一个Windows服务应用程序,我在其中创建WCF服务.
  • 其中一项服务是数据服务:通过WCF添加,删除,读取,更新数据.
  • WCF使用NHibernate进行数据操作

所以我的猜测是:

  • Hibernate使用WCF进行会话管理的任何建议(最佳实践)?

  • 任何人都知道

WcfOperationSessionContext(hibernate 3.0)类?

how to use it with WCF?
Run Code Online (Sandbox Code Playgroud)

好吧,使它具体化:

假设我有一个名为DataServices的 WCF服务

class WCFDataService .....
{

   void SaveMyEntity(MyEntity entity)
    {



         .....................?? // How to do? Best Way

         // Should i take one session  and use it all times
         // Should i take session and dipsose when operation finished then get 
         //new session for new operations?
         // If many clients call my WCF service function at the same time?
         // what may go wrong?
         // etc....


     }


 }
Run Code Online (Sandbox Code Playgroud)

我需要一个NHibernateServiceProvider

class NHibernateServiceProvider ....
{

    // How to get Session ?? Best way

     ISession GetCurrentSession(){.... }
     DisposeSession(){ ....}
}
Run Code Online (Sandbox Code Playgroud)

最好的祝愿

PS:我在这里和其他网页上都读过类似的条目.但看不出"具体"的答案.

Iul*_*scu 9

WcfOperationSessionContext类似于ThreadStaticSessionContext和WebRequestSessionContext,是会话上下文的实现.会话上下文用于将ISession实例绑定(关联)到特定上下文.

可以通过调用ISessionFactory.GetCurrentSession()来检索当前上下文中的会话.

你可以找到更多的信息在这里会话环境.

WcfOperationSessionContext表示跨越WCF操作的整个持续时间的上下文.您仍然需要在操作开始时处理会话的绑定,并在操作结束时处理会话的解除绑定/提交/处理.

要访问wcf管道中的开始/结束操作,您需要实现IDispatchMessageInspector.你可以在这里看到一个样本.

另外关于WCF集成:如果你使用ThreadStatic会话上下文它似乎可以在开发上工作,但是当wcf管道中的各种组件(例如:授权,身份验证)在不同的线程上执行时,你将在生产中遇到问题.

至于你几乎把它钉在最佳实践上:使用WcfOperationSessionContext存储当前会话和IDispatchMessageInspector来开始/完成你的工作单元.

编辑 - 解决您添加的详细信息:如果您按照上面的说明配置了WcfOperationSessionContext并执行绑定/解除绑定,您只需将ISessionFactory注入您的服务并使用factory.GetCurrentSession().如果时间允许,我会发布一个样本prj.

这是示例项目


Phi*_*rdt 5

我们用于管理与WCF的NHibernate会话的模型如下:

1)我们有自己的ServiceHost类,它继承自System.ServiceModel.ServiceHost,它也实现了ICallContextInitializer.我们将服务主机实例添加到服务中的每个操作,如下所示:

protected override void InitializeRuntime()
{
    base.InitializeRuntime();
    foreach (ChannelDispatcher cd in this.ChannelDispatchers)
    {
        foreach (EndpointDispatcher ed in cd.Endpoints)
        {
            foreach (DispatchOperation op in ed.DispatchRuntime.Operations)
            {
                op.CallContextInitializers.Add(this);
             }
        }
    }
}

public void AfterInvoke(object correlationState)
{
    // We don't do anything after the invoke
}

public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
    OperationContext.Current.Extensions.Add(new SessionOperationContext());
    return null;
}
Run Code Online (Sandbox Code Playgroud)

BeforeInvoke只是确保每个WCF调用的OperationContext都有自己的会话.我们发现IDispatchMessageInspector存在问题,其中会话在响应序列化期间不可用 - 如果使用延迟加载则会出现问题.

2)然后我们的SessionOperationContext将被调用以附加自身,我们使用OperationCompleted事件来移除自己.这样我们就可以确保会话可用于响应序列化.

public class SessionOperationContext : IExtension<OperationContext>
{

    public ISession Session { get; private set; }

    public static SessionOperationContext Current
    {
        get
        {
            OperationContext oc = OperationContext.Current;
            if (oc == null) throw new InvalidOperationException("Must be in an operation context.");
            return oc.Extensions.Find<SessionOperationContext>();
        }
    }

    public void Attach(OperationContext owner)
    {
        // Create the session and do anything else you required
        this.Session = ... // Whatever instantiation method you use

        // Hook into the OperationCompleted event which will be raised
        // after the operation has completed and the response serialised.
        owner.OperationCompleted += new EventHandler(OperationCompleted);
    }

    void OperationCompleted(object sender, EventArgs e)
    {
        // Tell WCF this extension is done
        ((OperationContext)sender).Extensions.Remove(this);
    }

    public void Detach(OperationContext owner)
    {
        // Close our session, do any cleanup, even auto commit 
        // transactions if required.
        this.Session.Dispose();
        this.Session = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们已经在高负载应用程序中成功使用了上述模式,它似乎运行良好.

总而言之,这类似于新的WcfOperationSessionContext所做的事情(当我们发现上面的模式时它不存在;-))但也克服了延迟加载的问题.

关于提出的其他问题:如果您使用上述模型,您只需执行以下操作:

void SaveMyEntity(MyEntity entity)
{
    SessionOperationContext.Current.Session.Save(entity);
}
Run Code Online (Sandbox Code Playgroud)

您可以保证会话始终存在,并且一旦WCF操作完成,它将被丢弃.如果需要,您可以以正常方式使用交易.


Nik*_*nis 3

这是一篇文章,详细描述了注册和使用 WcfOperationSessionContext 的所有步骤。它还包括将其与 agatha-rrsl 项目一起使用的说明。