How do I handle message failure in MSMQ bindings for WCF

前端 未结 4 1160
自闭症患者
自闭症患者 2020-12-29 07:10

I have create a WCF service and am utilising netMsmqBinding binding.

This is a simple service that passes a Dto to my service method and does not expect a response. T

4条回答
  •  温柔的废话
    2020-12-29 07:45

    If you're using SQL-Server then you should use a distributed transaction, since both MSMQ and SQL-Server support it. What happens is you wrap your database write in a TransactionScope block and call scope.Complete() only if it succeeds. If it fails, then when your WCF method returns the message will be placed back into the queue to be tried again. Here's a trimmed version of code I use:

        [OperationBehavior(TransactionScopeRequired=true, TransactionAutoComplete=true)]
        public void InsertRecord(RecordType record)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
                {
                    SqlConnection InsertConnection = new SqlConnection(ConnectionString);
                    InsertConnection.Open();
    
                    // Insert statements go here
    
                    InsertConnection.Close();
    
                    // Vote to commit the transaction if there were no failures
                    scope.Complete();
                }
            }
            catch (Exception ex)
            {
                logger.WarnException(string.Format("Distributed transaction failure for {0}", 
                    Transaction.Current.TransactionInformation.DistributedIdentifier.ToString()),
                    ex);
            }
         }
    

    I test this by queueing up a large but known number of records, let WCF start lots of threads to handle many of them simultaneously (reaches 16 threads--16 messages off the queue at once), then kill the process in the middle of operations. When the program is restarted the messages are read back from the queue and processed again as if nothing happened, and at the conclusion of the test the database is consistent and has no missing records.

    The Distributed Transaction Manager has an ambient presence, and when you create a new instance of TransactionScope it automatically searches for the current transaction within the scope of the method invokation--which should have been created already by WCF when it popped the message off the queue and invoked your method.

提交回复
热议问题