交易仅在客户端启动

时间:2011-07-15 14:54:44

标签: wcf

我需要实现以下场景: 如果客户端启动事务,它将流向服务器,但如果客户端未启动事务,则必须在没有事务的情况下执行服务方法。可能吗?就我而言,如果没有TransactionScopeRequired = true,事务就不会流动。

服务器:

 <system.serviceModel>
  <bindings>
   <netTcpBinding>
    <binding name="tcpTransactional" transactionFlow="true" />
   </netTcpBinding>
  </bindings>
  <services>
   <service name="WcfServiceLibrary1.TcpTransactionalService">
    <endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpTransactional"
     contract="WcfServiceLibrary1.ITcpTransactionalService">
     <identity>
      <dns value="localhost" />
     </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
     contract="IMetadataExchange" />
    <host>
     <baseAddresses>
      <add baseAddress="http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary1/TcpTransactionalService/" />
      <add baseAddress="net.tcp://localhost:8730/Design_Time_Addresses/WcfServiceLibrary1/TcpTransactionalService/" />
     </baseAddresses>
    </host>
   </service>
  </services>
  <behaviors>
   <serviceBehaviors>
    <behavior>
     <!-- To avoid disclosing metadata information, 
     set the value below to false and remove the metadata endpoint above before deployment -->
     <serviceMetadata httpGetEnabled="True"/>
     <!-- To receive exception details in faults for debugging purposes, 
     set the value below to true. Set to false before deployment 
     to avoid disclosing exception information -->
     <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
 </system.serviceModel>

    [ServiceContract]
    public interface ITcpTransactionalService
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        void DoWork();
    }

    //[OperationBehavior(TransactionScopeRequired = true)]
    public void DoWork()
    {
      Debug.Assert(Transaction.Current != null);
      Debug.Assert(Transaction.Current.TransactionInformation.DistributedIdentifier != Guid.Empty);
    }


客户端:

<system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_ITcpTransactionalService" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          transactionFlow="true" transferMode="Buffered" transactionProtocol="OleTransactions"
          hostNameComparisonMode="StrongWildcard" listenBacklog="10"
          maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
          maxReceivedMessageSize="65536">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
            enabled="false" />
          <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
            <message clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://localhost:8730/Design_Time_Addresses/WcfServiceLibrary1/TcpTransactionalService/"
        binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ITcpTransactionalService"
        contract="TcpTransactionalService.ITcpTransactionalService"
        name="NetTcpBinding_ITcpTransactionalService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

    private static void TestTcp()
    {
      using (var scope = new TransactionScope())
      {
        var client = new TcpTransactionalService.TcpTransactionalServiceClient();
        client.DoWork();

        Debug.Assert(Transaction.Current != null);
        Debug.Assert(Transaction.Current.TransactionInformation.DistributedIdentifier != Guid.Empty);

        scope.Complete();
      }
    }

1 个答案:

答案 0 :(得分:1)

使用TransactionScopeRequire = true

如果客户端未发送事务,则不会以分布式事务结束。如果它确实那么你做

现在,这仍然会在本地事务中调用您的操作。如果要禁止此操作,请检查分布式标识符。如果它的Guid.Empty在另一个像这样创建的TransactionScope中运行其余的代码:

 if (Transaction.Current.TransactionInformation.DistributedIdentifier == Guid.Empty)
 {
    using (var scope = new TransactionScope(TransactionScopeOption.Suppress))
    {
       DoWork();
       scope.Complete();
    }
 }
 else
 {
        DoWork();
 }