Reputation: 3465
I have a .NET TransactionScope that needs to contain both a MSSQL database and a IBM MQ queue.
I'm using .NET 4.0 (VS2010), SQL 2008R2, MQ Server 6.0, MQ Client 7.0.1.9 in fully managed mode. All components are running on different machines.
From what I've found the following pattern should work: http://publib.boulder.ibm.com/infocenter/wmqv7/v7r1/index.jsp?topic=%2Fcom.ibm.mq.doc%2Fun11400_.htm
Implicit Transaction The following piece of code describes how a WebSphere MQ .NET application puts a message using .NET implicit transaction programming.
Using (TransactionScope scope = new TransactionScope ()) { Q.Put (putMsg,pmo); scope.Complete (); }
Q.close(); qMgr.Disconect();}
In my code this looks like:
// mq properties
properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
properties.Add(MQC.HOST_NAME_PROPERTY, HOSTNAME);
properties.Add(MQC.PORT_PROPERTY, PORTNUMBER);
properties.Add(MQC.CHANNEL_PROPERTY, CHANNELNAME);
_queueManager = new MQQueueManager(queueManagerName, properties);
_queue = _queueManager.AccessQueue(queueName, MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
_gmo = new MQGetMessageOptions();
_gmo.Options |= MQC.MQGMO_WAIT;
_gmo.Options |= MQC.MQGMO_SYNCPOINT;
_gmo.WaitInterval = 1000; // 1 seconds wait
// in a loop
using (TransactionScope t = new TransactionScope())
{
var message = new MQMessage();
try
{
_queue.Get(message, _gmo);
}
catch (MQException mqe)
{
message = null;
if (mqe.ReasonCode == 2033)
{
Console.WriteLine("No message available");
}
else
{
throw;
}
}
t.Complete();
}
//Afterwards:
if (_queue != null)
{
_queue.Close();
_queue = null;
}
if (_queueManager != null)
{
_queueManager.Disconnect();
_queueManager.Close();
_queueManager = null;
}
The problem with this is that all messages re-appear in the queue after the application is closed, while the work in the SQL database is committed. If an exception happens inside the transactionscope, the SQL transaction rolls back while the messages in MQ appear to stay removed (until I restart the application). Also, I don't see any DTC activity between the .NET client and the MQ server (is that expected?)
I'm kind of lost here, any help is greatly appreciated.
UPDATE
Upvotes: 3
Views: 5182
Reputation: 15273
Well, you need to have at least WebSphere MQ v7.1, both client and queue manager, installed to run global transactions in fully managed mode using the TransactionScope. MS DTC will be the transaction coordinator in this case. The InfoCenter link you posted about is actually pointing to WebSphere MQ v7.1.
Update:
Prior to MQ v7.1, XA transactions are supported only in Unmanaged mode with MTS as the transaction coordinator. Sample code for distributed transaction in unmanaged mode is here. You will require an additional component, Extended Transaction Client(XTC) to be installed. As per latest announcements the XTC is available for free. The installable can be found in your MQ Server installation image.
When a MQ connection is disconnected (basically MQDISC is called), any uncommitted messages in a transaction will be rolled back. Because of this messages reappear on the queue.
Upvotes: 4