WCF Transactional Queue vs Non-Transaction Queue

If queue message is part of transaction process then we could consider two cases

Case1: message must not queue up in MSMQ if one of transaction scope statement  fails
Case2: message should queue up even if one of transaction statement fails

Without further due straight jump to quick example

# STEP 1: Create transactional queue name “msmqtest”

# STEP 2: Data contract

[DataContract]    
public class Message
{
  [DataMember]
  public string payload;
}

# STEP 3: Create service contract

[ServiceContract]
public interface IRequestService
{        
  [OperationContract(IsOneWay=true)]
  void ProcessRequest(Message msg);
}

# STEP 4: Impletement service contract

public class RequestService : IRequestService
{
  public void ProcessRequest(Message msg)
  {
      Console.WriteLine(String.Format("Received message at {0} : {1}", DateTime.Now, msg.payload));
  }                
}

# STEP 5: Service Self Hosting

class SelfHost
{
  public static void HostMSMQService()
  {
      using (ServiceHost sht = new ServiceHost(typeof(WCFSelfHosting.Services.RequestService)))
      {                
          NetMsmqBinding nbind = new NetMsmqBinding(NetMsmqSecurityMode.None);          
          sht.AddServiceEndpoint(new ServiceEndpoint(ContractDescription.GetContract(typeof(WCFSelfHosting.Contract.IRequestService)), nbind, new EndpointAddress("net.msmq://localhost/private/msmqtest")));
          sht.Open();
          Console.WriteLine("Please enter to stop service");
          Console.Read();
          sht.Close();
      }
  }
}

# STEP 6: Create client for different cases (i.e  transaction pass, fail and process without transaction scope)

class Program
{
  static void Main(string[] args)
  {
      NetMsmqBinding nmsmq = new NetMsmqBinding(NetMsmqSecurityMode.None);            
      using (ChannelFactory chf = new ChannelFactory(nmsmq, new EndpointAddress("net.msmq://localhost/private/msmqtest")))
      {
          chf.Open();

          // CASE 1
          using (TransactionScope transScope = new TransactionScope(TransactionScopeOption.Required))
          {
              WCFSelfHosting.Contract.IRequestService srv = chf.CreateChannel();
              srv.ProcessRequest("Transaction Fail Message");

              int j = 0;
              int i = 100 / j;
              transScope.Complete();
          }

          using (TransactionScope transScope = new TransactionScope(TransactionScopeOption.Required))
          {
              WCFSelfHosting.Contract.IRequestService srv = chf.CreateChannel();
              srv.ProcessRequest("Transaction PASS Message");

              int j = 10;
              int i = 100 / j;
              transScope.Complete();
          }

          // CASE 2
          WCFSelfHosting.Contract.IRequestService srv = chf.CreateChannel();
          srv.ProcessRequest("Transaction Scope Message");

          int j = 0;
          int i = 100 / j;

          chf.Close();
      }
   }
}

# Start service client and check private queue two messages are queued

Yes you guessed it right !!! Due to transaction fail first message is not queued

transaction_img

# Start service and check which message we are pulled to reconfirm

service_msg

***Analysis on WCF Transactional Queue vs Non-Transaction Queue

– Firstly, transaction scope works because “msmqtest” is transactional queue
– Food for thought what if there is non-transactional, does TransactionScope make sence or worth to use ?

I say no…

Advertisements