【发布时间】:2016-11-16 14:27:33
【问题描述】:
我正在使用TransactionScope [.Net transactions] 编写一个 .NET 应用程序。代码是一个使用相同MQQueueManager 实例的简单循环:
- 从主题订阅中接收
- 保存到 MSSQL 数据库
- 将翻译后的消息发送到另一个主题
- 提交交易
当我到达循环顶部以获取新消息时,我收到了 MQRC_GLOBAL_UOW_CONFLICT 异常。
我了解事务提交是异步的,队列管理器可能尚未准备好参与新事务。我如何确定它已准备就绪?我在Transaction.Current 上订阅了TransactionCompleted 事件,并在重新进入循环之前等待它触发。同样的例外。我可以通过休眠 10 毫秒来避免异常,但我不想为此设置硬超时。必须有一个“正确”的方式来知道。
代码:
class Program
{
public static bool tranDone = false;
static void Main(string[] args)
{
Hashtable properties = new Hashtable();
properties.Add(MQC.HOST_NAME_PROPERTY, "server");
properties.Add(MQC.PORT_PROPERTY, 1414);
properties.Add(MQC.CHANNEL_PROPERTY, "SYSTEM.DEF.SVRCONN");
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
MQQueueManager mgr = new MQQueueManager("QManager", properties);
MQTopic topicIn = mgr.AccessTopic("TopicString", "TopicName",
MQC.MQSO_DURABLE | MQC.MQSO_RESUME | MQC.MQSO_MANAGED | MQC.MQSO_FAIL_IF_QUIESCING,
null, "SubscriptionName");
MQTopic topicOut = mgr.AccessTopic(
"TopicString2", "TopicName",
MQC.MQTOPIC_OPEN_AS_PUBLICATION,
MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING);
MQGetMessageOptions gmo = new MQGetMessageOptions
{
Options = MQC.MQGMO_WAIT | MQC.MQGMO_SYNCPOINT,
// 1 minute wait
WaitInterval = 1000 * 60
};
MQPutMessageOptions pmo = new MQPutMessageOptions
{
Options = MQC.MQPMO_SYNCPOINT,
};
while (true)
{
try
{
using (TransactionScope ts = new TransactionScope())
{
Transaction.Current.TransactionCompleted += Current_TransactionCompleted;
MQMessage msgIn = new MQMessage();
topicIn.Get(msgIn, gmo);
string text = msgIn.ReadString(msgIn.MessageLength);
Console.WriteLine($"Message Received: {text}");
MQMessageContext context = new MQMessageContext();
context.Messages.Add(new Message() { Content = text });
context.SaveChanges();
Console.WriteLine("Added to DB");
MQMessage msgOut = new MQMessage();
string ttext = $"translated: {text}";
msgOut.WriteString(ttext);
topicOut.Put(msgOut, pmo);
Console.WriteLine($"Message Sent: {ttext}");
msgIn.ClearMessage();
Console.Write("Commit? [Y/N/Q]: ");
string response = Console.ReadLine();
if ("y" == response.ToLower())
{
ts.Complete();
Console.WriteLine("Transaction Committed");
}
else if ("q" == response.ToLower())
{
Console.WriteLine("Quitting");
break;
}
}
}
catch (MQException mqe)
when (MQC.MQRC_NO_MSG_AVAILABLE == mqe.ReasonCode)
{
Console.WriteLine("Msg not available in interval");
continue;
}
while (!tranDone)
{
Thread.Sleep(2);
}
tranDone = false;
}
}
private static void Current_TransactionCompleted(object sender, TransactionEventArgs e)
{
tranDone = true;
}
}
【问题讨论】:
-
发布您的代码可能有助于更好地理解问题
-
除了 MQ 之外,您还为您的全局事务添加了哪些其他资源?即为什么您使用全局事务而不是仅 MQ 事务?
-
@MoragHughson Microsoft SQLServer。 MQMessageContext 携带数据库连接并在 context.SaveChanges() 上提交
-
@Shashi。我没有连接到队列管理器的问题。不确定要在您链接的页面中查找什么。
标签: .net transactions ibm-mq