【问题标题】:Removing message from MSMQ in case of deserialization exception在反序列化异常的情况下从 MSMQ 中删除消息
【发布时间】:2020-01-27 19:54:18
【问题描述】:

目前我正在处理从本地私有 MSMQ 接收消息的寡妇服务。队列是事务性的。

接收是这样完成的:

public void ReceiveAndSaveData(MessageQueue queue, MsmqDbContext context)
        {
            var message = new Message();
            try
            {
                using (var tx = new MessageQueueTransaction())
                {
                    tx.Begin();
                    message = queue.Receive(tx);
                    var bodyReader = new StreamReader(message.BodyStream);
                    var jsonBody = bodyReader.ReadToEnd();
                    var messageData = JsonConvert.DeserializeObject<QueueMessage>(jsonBody);

                    /*THERE IS SOME DATA PROCESSING*/


                    tx.Commit();
                }
            }
            catch (JsonSerializationException e)
            {
                Logger.WriteError(new LogDetail("Error occured during deserializing incoming data.", e, message.Id));

            }
            catch (Exception e)
            {
                Logger.WriteError(new LogDetail("Error occured during saving data to database", e, message.Id));
            }
        }

如果发生 JsonSerializationException,我想从当前队列中删除这条消息。有人知道如何解决这个问题吗?

【问题讨论】:

  • MSDN try-catch-finally。在适当的捕获中,删除消息并在 finally 块中执行提交。
  • 将 try catch 移入 using 语句并 try tx.Abort();在失败的情况下。
  • 但是在这种情况下你能分享如何从队列中删除当前消息的代码吗?

标签: c# .net msmq


【解决方案1】:

使用 Abort() 方法并将 tx-object 创建移到 try-catch 块之外。

public void ReceiveAndSaveData(MessageQueue queue, MsmqDbContext context)
{
    bool exceptionOccurred = false;
    var message = new Message();
    MessageQueueTransaction tx;
    try
    {
        exceptionOccurred = false;
        using (tx = new MessageQueueTransaction())
        {
            tx.Begin();
            message = queue.Receive(tx);
            var bodyReader = new StreamReader(message.BodyStream);
            var jsonBody = bodyReader.ReadToEnd();
            var messageData = JsonConvert.DeserializeObject<QueueMessage>(jsonBody);

            /*THERE IS SOME DATA PROCESSING*/

        }
    }
    catch (JsonSerializationException e)
    {
        Logger.WriteError(new LogDetail("Error occured during deserializing incoming data.", e, message.Id));
        tx.Abort(); //Rolls back the pending internal transaction
        exceptionOccurred = true;
    }
    catch (Exception e)
    {
        Logger.WriteError(new LogDetail("Error occured during saving data to database", e, message.Id));
         exceptionOccurred = true;
    }
    finally
    {
        if(!exceptionOccurred)
            tx.Commit();
    }
}

Abort() MSDN

【讨论】:

  • 我已经尝试过了,但在 catch 块中出现错误,其中 tx 有错误使用未分配的局部变量 'tx' 并且在 RemoveCurrent 上出现错误,即 MessageQueueTransaction 不包含 'RemoveCurrent 的定义'
  • 抱歉,这里的new Message() 是什么?无论如何,我更新了我的答案以使用 Abort 方法。
  • 我已经删除了消息变量的初始化,但我仍然有 tx 变量的问题。如果我不在 try catch 块之外对其进行初始化,我将无法使用它。仅供参考。 tx.Abort() 从队列中删除消息?
  • 嗯,奇怪。你可以试试message.RemoveCurrent(tx); 吗? .Abort() 回滚内部事务。
  • message.RemoveCurrent(tx) 抛出相同的错误。方法 RemoveCurrent 在消息对象上未知
【解决方案2】:

tx.Commit() 也放在JsonSerializationExceptioncatch 块内

【讨论】:

  • tx.Commit() 在 try 块中实例化,因此与 catch 不在同一范围内(即不可用)
  • 你可以将 try-catch 块移到 using 块中,因为反序列化操作是在 using 语句中执行的。
猜你喜欢
  • 1970-01-01
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 2017-11-12
  • 2013-07-02
  • 2013-02-13
  • 2023-03-17
相关资源
最近更新 更多