IBM MQ 交易和 .net

IBM MQ transactions and .net

我使用 .net C#(IBM MQ 版本 9.1.5)从队列中提取消息。所以我没有问题连接到队列和获取消息。 我看过有交易的概念Distributed Transactions.

我尝试了以下方法:

var getMessageOptions = new MQGetMessageOptions();
getMessageOptions = new MQGetMessageOptions();
getMessageOptions.Options += MQC.MQGMO_WAIT + MQC.MQGMO_SYNCPOINT;
getMessageOptions.WaitInterval = 20000;  // 20 seconds wait

Transaction oldAmbient = Transaction.Current;
using (var tx = new CommittableTransaction())
{   
  try
  {
    int i = queue.CurrentDepth;
    Log.Information($"Current queue depth is {i} message(s)");
    var message = new MQMessage();
    queue.Get(message, getMessageOptions);

    string messageStr = message.ReadString(message.DataLength);
    Log.Information(messageStr);

    tx.Commit();
  }
  catch (MQException e) when (e.Reason == 2033)
  {
   // Report exceptions other than "no messages in the queue"
   Log.Information("No messages in the queue");
   tx.Rollback();
  }
  catch (Exception ex)
  {
   Log.Error($"Exception when trying to capture a message from the queue: {ex.Message}");
   tx.Rollback();
  }

我收到错误代码 2035。

查看 Recovering Transactions 上的文档,"SYSTEM.DOTNET.XARECOVERY.QUEUE" 住在哪里,是在 queuemanger 上吗? 我需要为此启用权限吗?

我还看到提到了 Microsoft 分布式事务管理器,这是我们需要在本地主机上 运行 才能使分布式事务工作的东西吗?

如果正在使用 MQ 分布式事务功能,那么用户 运行 应用程序应该有权 "SYSTEM.DOTNET.XARECOVERY.QUEUE"。如果事务不完整 "SYSTEM.DOTNET.XARECOVERY.QUEUE" 队列保存不完整的信息交易作为该队列中的消息,稍后可用于解决交易。

根据您在评论中提出的方案,即“我们只想将消息保存到文件中。我的想法是,如果这有问题,我可以回滚事务." 。如果 MQ 是唯一的资源管理器,那么您不必使用分布式事务。在同步点下获取消息也可以用来代替分布式事务。如果使用多个资源管理器,分布式事务将很有用。

要在同步点下获取消息,可以通过更新主机名、通道、端口、队列和队列管理器名称来使用以下示例代码:

    var getMessageOptions = new MQGetMessageOptions();
    getMessageOptions = new MQGetMessageOptions();
    getMessageOptions.Options += MQC.MQGMO_WAIT + MQC.MQGMO_SYNCPOINT;
    getMessageOptions.WaitInterval = 20000;  // 20 seconds wait
    Hashtable props = new Hashtable();
    props.Add(MQC.HOST_NAME_PROPERTY, "localhost");
    props.Add(MQC.CHANNEL_PROPERTY, "DOTNET.SVRCONN");
    props.Add(MQC.PORT_PROPERTY, 3636);
    MQQueueManager qm = new MQQueueManager("QM", props);
    MQQueue queue = qm.AccessQueue("Q1", MQC.MQOO_INPUT_AS_Q_DEF);

    try
    {
        var message = new MQMessage();
        queue.Get(message, getMessageOptions);
        //to commit the message
        qm.Commit();
        string messageStr = message.ReadString(message.DataLength);
    }
    catch (MQException e) when (e.Reason == 2033)
    {
       // Report exceptions other than "no messages in the queue"
         Log.Information("No messages in the queue");   
    }
    catch (Exception ex)
    {
      Log.Error($"Exception when trying to capture a message from the queue: 
    }