[WCF Transaction] 4. 事务与会话

来源:互联网 发布:中国联通wap网络 编辑:程序博客网 时间:2024/05/30 13:42

我们看下面的例子。

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IService
{
  [OperationContract]
  [TransactionFlow(TransactionFlowOption.Allowed)]
  void Test();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IService, IDisposable
{
  public MyService()
  {
    Console.WriteLine("Constructor...");
  }

  public void Dispose()
  {
    Console.WriteLine("Dispose...");
  }

  [OperationBehavior(TransactionScopeRequired = true)]
  public void Test()
  {
  }
}

public class WcfTest
{
  public static void Test()
  {
    AppDomain.CreateDomain("Server").DoCallBack(delegate
    {
      NetTcpBinding bindingServer = new NetTcpBinding();
      bindingServer.TransactionFlow = true;

      ServiceHost host = new ServiceHost(typeof(MyService), new Uri("net.tcp://localhost:8080"));
      host.AddServiceEndpoint(typeof(IService), bindingServer, "");
      host.Open();
    });

    NetTcpBinding bindingClient = new NetTcpBinding();
    bindingClient.TransactionFlow = true;

    IService client = ChannelFactory<IService>.CreateChannel(bindingClient,
     new EndpointAddress("net.tcp://localhost:8080"));

    using (TransactionScope scope = new TransactionScope())
    {
      using (client as IDisposable)
      {
        client.Test();
        client.Test();

        scope.Complete();
      }
    }
  }
}


输出:
Constructor...
Dispose...
Constructor...
Dispose...

看输出结果,有没有感觉到奇怪?服务明明是 PreSession 模式,为什么每次调用完 Test() 后,服务实例会被释放?其实这是ServiceBehavior 的 ReleaseServiceInstanceOnTransactionComplete属性在作怪,它的缺省值是 true,表示每次完成事务(完成投票)后立即释放服务实例。好了,我们修改这个默认值。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
  ReleaseServiceInstanceOnTransactionComplete = false)]
public class MyService : IService, IDisposable
{
  ...
}


这回输出结果就符合我们最初的设想了。

另外要注意的是,启用事务支持且 ReleaseServiceInstanceOnTransactionComplete = True 时,ConcurrencyMode 必须等于 ConcurrencyMode.Single,否则会引发异常。

在上一章我们提到,如果 TransactionAutoComplete = false,那么就需要我们手动使用"OperationContext.Current.SetTransactionComplete();"进行投票,其实还有另外一个方法就是使用 ServiceBehavior 的TransactionAutoCompleteOnSessionClose 属性,它的意思很简单,就是在会话结束的时候自动进行投票。缺省值为False。

 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
  ReleaseServiceInstanceOnTransactionComplete = false,
  TransactionAutoCompleteOnSessionClose = true)]
public class MyService : IService, IDisposable
{
  [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
  public void Test()
  {
  }
}


客户端调用方法也有些讲究。方法2为什么会失败,想想 TransactionAutoCompleteOnSessionClose 的名字就明白了。

方法1:正确执行

 
using (TransactionScope scope = new TransactionScope())
{
  using (client as IDisposable)
  {
    client.Test();
    client.Test();

    scope.Complete();
  }
}


方法2:事务中止,引发异常。

using (client as IDisposable)
{
  using (TransactionScope scope = new TransactionScope())
  {
    client.Test();
    client.Test();

    scope.Complete();
  }
}
原创粉丝点击