Transferred from: http://www.cnblogs.com/daxnet/archive/2011/03/15/1984995.html
. NET provides access support for MSMQ directly, you can easily manipulate MSMQ by adding system.messaging assembly references. MSMQ supports two transactional modes: internal transaction processing and MS-DTC-based distributed transaction processing.
Internal transaction processing for MSMQ
Internal transaction processing for MSMQ means that transaction processing is done only with the transaction mechanism provided by MSMQ itself. For example, if you have a series of messages that need to be published to MSMQ, you can start an internal transaction to ensure that the publishing process for these messages is an atomic operation. To use the internal transaction mechanism of MSMQ, when creating a message queue, you need to tick the "transactional" option, as shown in:
First, you need to create an MessageQueueTransaction object and use the begin call to start the internal Transact-processing of MSMQ. Then, in the MessageQueue send method, the message is sent using the overloaded function of Send (object, messagequeuetransaction). The created MessageQueueTransaction object is passed as the second argument to the Send method, and the commit method of the MessageQueueTransaction object is used to commit the transaction after all messages have been sent. If a problem is encountered during the sending of a message, the abort call to the MessageQueueTransaction object is used to rollback the transaction. See the sample code below:
Hide line number copy code ? Internal transaction processing for MSMQ
False, False, queueaccessmode.sendandreceive))
{
MessageQueueTransaction trans = new MessageQueueTransaction ();
Try
{
Trans. Begin ();
for (int i = 0; i < 5; i++)
{
Messagequeue.send (New Message (i), trans);
}
Trans.commit ();
}
Catch
{
Trans. Abort ();
}
Messagequeue.close ();
}
Note: If your message queue does not have the "transactional" option set when it is created, you will not be able to modify this option after the creation of the message queue. Even worse, executing the above code on a non-transactional queue does not publish the message to the message queue, and the framework itself does not prompt any error messages indicating that the message was not published successfully.
Using MSMQ in Distributed transaction processing
In the context of distributed transactions (for example, in the TransactionScope of. NET 2.0+), the messagequeuetransaction mentioned above will be useless, that is to say, MessageQueueTransaction has nothing to do with distributed transaction processing. All you have to do is initialize an instance of MessageQueue in a normal way, and then call the Send method to publish the message and, when you publish the message, tell MessageQueue by setting the value of MessageQueueTransactionType. is currently in the context of a distributed transaction. Therefore, you need to use the overloaded method of Send/receive: Send (object, MessageQueueTransactionType) and receive (MessageQueueTransactionType). As follows:
Hide line number copy code ? MSMQ calls in a distributed transaction
using (TransactionScope transaction = new TransactionScope ())
{
Message inputmsg = inputqueue.receive (messagequeuetransactiontype.automatic);
Do some
Transaction.complete ();
}
Note: For some relatively long-life transactions, for example, suppose your use case is this: you first need to get the message from a message queue and then update your database records, then your code might look like this:
Hide line number copy code ? MSMQ calls in a distributed transaction
using (TransactionScope transaction = new TransactionScope ())
{
using (MessageQueue somequeue = new MessageQueue ("<queue connection>"))
{
Message msg = somequeue.receive ();
Do something else
}
Transaction.complete ();
}
It's not right to do this! Because the Receive method is a synchronous call, if there is nothing at all in the message queue, the receive call is blocked until a new message appears in the message queue. This means that your distributed transactions are always in an open state, and may cause timeouts due to long wait times, resulting in a messagequeueexception.
The correct approach is to use the BeginPeek call on MessageQueue (note: Not the BeginReceive method, because the BeginReceive method is not used to process the transactional queue), and then subscribe to the Peekcomplete event, In the process of event processing, the use of TransactionScope and receive methods to achieve the acquisition of messages. For example:
Hide line number copy code
MessageQueue inputqueue = new MessageQueue ("<queue connection>");
Inputqueue.peekcompleted + = (s, e) = =
{
using (TransactionScope transaction = new TransactionScope ())
{
Message inputmsg = inputqueue.receive (messagequeuetransactiontype.automatic);
Do some
Transaction.complete ();
}
Inputqueue.beginpeek ();
};
Inputqueue.beginpeek ();
Finally, to remind you that if you want to do things that are limited to dealing with MSMQ, you can use the internal transaction processing mechanism of MSMQ, after all, using Distributed transaction processing involves MS-DTC, which can lead to excessive overhead and impact performance.
. NET Distributed Transaction processing summary "under"-Distributed transaction processing with MSMQ