Transaction started only on client side

I need to implement the following scenario: If client starts transaction it flow to server, but if client doesn't start transaction, service method must be executed without transaction. Is it possible? In my case, transaction doesn't flow without TransactionScopeRequired=true.

Server:

 <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);
    }


Client:

<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();
      }
    }

Use TransactionScopeRequire=true

If the client doesn't send a transaction you don't end up in distributed transaction. if it does then you do

Now this will still call your operation in a local transaction. If you want to suppress this then check the distributed identifier. If its Guid.Empty run the rest of the code in another TransactionScope created like this:

 if (Transaction.Current.TransactionInformation.DistributedIdentifier == Guid.Empty)
 {
    using (var scope = new TransactionScope(TransactionScopeOption.Suppress))
    {
       DoWork();
       scope.Complete();
    }
 }
 else
 {
        DoWork();
 }
链接地址: http://www.djcxy.com/p/95930.html

上一篇: 如何解决WCF中的System.ServiceModel.ServerTooBusyException?

下一篇: 交易仅在客户端开始