2012-08-03 57 views
2

幾個星期以來,我一直與Service Broker一起工作,在跟蹤對話的同時,我發現了一些奇怪的事情......對話似乎在隊列中還有一個額外的消息,導致發生錯誤。SQL Server Service Broker隊列對話對話框

從我的理解,對話對話框應該如下:

  1. 觸發火災和電話開始交談
  2. 發起服務場所消息隊列
  3. 目標服務大火一個存儲過程,接收消息並結束對話
  4. 啓動器服務觸發存儲的進程,接收消息並結束對話。

發生了什麼是在隊列末尾有一個額外的消息,它再次觸發存儲的proc,但細節(即conversation_handle)爲空。它也會拋出一個錯誤:Conversion failed when converting from a character string to uniqueidentifier.爲了解決這個錯誤,我將conversation_handle轉換爲varchar,然後檢查null。對我來說似乎很愚蠢,我必須這樣做。

更新:錯誤已經消失 - 我相信它發生時,我試圖登錄的conversation_handle(這是無效)。

什麼是結束對話而不在最後得到額外消息的正確方法?

這是我現在有:

alter proc dbo.MessageProcessor 
as 

begin 

    set nocount on; 
    set xact_abort on; 

    declare @xactState smallint 

    declare @handle uniqueidentifier, 
      @responseXml xml, 
      @messageType sysname; 

    begin transaction; 
    begin try 

     ;receive top(1) 
      @messageType = message_type_name, 
      @handle = conversation_handle, 
      @responseXml = message_body 
     from dbo.MessageQueue 

     if(@handle is not null) 
     begin 

      if (@messageType = N'DEFAULT') 
      begin 

       save transaction MessageProcessor_Tran 

       begin try 

        -- doing work here 

       end try 
       begin catch 

        select @xactState = xact_state() 

        if(@xactState = -1) 
        begin 
         rollback; 
         raiserror(N'Unrecoverable error', 16, 1) 
        end 
        else if(@xactState = 1) 
        begin 
         rollback transaction MessageProcessor_tran 
        end 

        -- log error information 

       end catch 
      end 
      else if (@messageType = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error') 
      begin 
       declare @errorNumber int, 
         @errorMessage nvarchar(4000); 

       with xmlnamespaces (DEFAULT N'http://schemas.microsoft.com/SQL/ServiceBroker/Error') 
       select @errorNumber = @responseXml.value ('(/Error/Code)[1]', 'INT'), 
        @errorMessage = @responseXml.value ('(/Error/Description)[1]', 'NVARCHAR(4000)'); 
       -- log error 
      end 

      end conversation @handle 
      set @handle = null 
     end 

     commit 
    end try 

    begin catch 

     declare @error int, 
       @message nvarchar(2048) 

     select @error = error_number(), 
      @message = error_message(), 
      @xactState = xact_state(); 

     if(@xactState <> 0) 
      rollback; 

     if(@handle is not null) 
      end conversation @handle; 

     -- log error    
     raiserror(N'Error: %i, %s', 1, 60, @error, @message) with log; 

    end catch 
end 
go 
+0

什麼是您的「流氓」消息的消息類型? – 2012-08-03 01:31:59

+0

它也是NULL。 – 2012-08-03 01:34:05

回答

2

沒有任何額外的信息。只是你的程序在空隊列上被激活。您激活的過程代碼應該被激活,並且RECEIVE會每隔一段時間返回一個空的行集(如果您每次只用一條消息測試它,就會發生每次都如您所見的實際負載情況,它很少會發生) 。

在您的代碼中,這種情況(接收空結果集)將反映在NULL @handle,NULL @messageType和NULL @responseXML中,這幾乎就是您所描述的。

+0

再次感謝Remus。 – 2012-08-03 20:08:34

相關問題