Transactional Message Processing
Transactional processing allows you to ensure that the messages in a transaction are delivered in order, are delivered only once, and are successfully retrieved from the destination queue. The MessageQueue component can be used to send and receive messages transactionally. When you send messages inside a transaction, you group a set of related messages. All the messages contained in the transaction are either delivered together in the order in which they were sent (a committed transaction), or automatically not sent or received if any problems occur (an aborted transaction).
There are two main types of transactions you can create from your applications:
Internal transactions are used to send messages between two or more Message Queuing resources — that is, between two queues belonging to a Message Queuing enterprise.
External transactions are used to send messages between queues and other resources, such as databases.
Internal and external transactions differ in their programming model, in the resource manager used to govern the transaction, and in their usage patterns.
Internal transactions are executed by creating an instance of the MessageQueueTransaction class and associating it with an instance of the MessageQueue component. An internal transaction is the simplest type of transaction. Messages are sent between one or more message queues, and Message Queuing's transaction coordinator governs the actions that occur. Because you control these steps in the process manually, internal transactions can be thought of as manual or explicit transactions, whereas external transactions are automatic or implicit.
The programming model for internal transactions are very simple — you call the Begin method of the MessageQueueTransaction class and pass an instance of this class to the sending or receiving method. You then call Commit to save the transaction's changes to the destination queue. For more information, see How to: Send Messages Within Internal Transactions.
Internal transactions are somewhat limited in functionality, in that you cannot perform transactions with non-message queuing resources such as databases. If you want to interact with a database in a transaction, you must use external transactions. However, in spite of these limitations, internal transactions have better performance than external transactions.
Both internal and external transactions require that you send the messages to a queue that has been marked as transactional. For more information, see How to: Create Transactional Queues.
External transactions are typically used when you want to send messages between queues and another type of resource. For example, you might want to retrieve a message from a queue and send it to a database, or vice versa. External transactions differ from internal transactions in several ways:
External transactions rely on a coordinator that is not part of the Message Queuing system. In most cases, this will be the Microsoft Distributed Transaction Coordinator (DTC). The DTC enlists the necessary resources in the transaction and governs the process of determining whether all of the actions in the transaction succeed or fail as a unit.
An external transaction has a more complex programming model. Instead of simply calling Begin, Commit, and Abort, you specify attributes that indicate an external transaction and register the component with COM+ 1.0 Services. You also must use a special form of the Send and Receive methods that takes a parameter for the type of transaction, and set this field to Automatic.
There are also other types of transactions that can be sent without using the MessageQueue component. For more information on transactions in Visual Studio or the .NET Framework, see the following topics:
For more information on
An example demonstrating the attributes used with external transactions
See MSDN online.
Transactions in C++