ServiceBroker:存储过程作为独立工作但不作为触发器工作

问题描述

我们正在尝试从 sql Server 异步启动 Web 服务,而 Service broker 似乎是最有趣的选择。

对于 Service broker 本身,可以在网上找到许多不同的示例。我设法有一个工作示例,其中我在队列上的消息中发送了几个参数,并在消息到达时自动触发队列。 问题是当我只是将信息保存到另一个表时,代码工作正常,但当我尝试调用 Web 服务时却失败了。然后它具有停止队列的效果
当我单独运行存储过程但不是作为队列上的触发器时,它仍然有效。 有没有人知道我做错了什么?

我从队列中获取消息的存储过程如下:

CREATE PROCEDURE usp_CommandLauncher
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @RecvReqDlgHandle AS UNIQUEIDENTIFIER;
    DECLARE @RecvReqMsg AS nvarchar(max);
    DECLARE @RecvReqMsgName AS sysname;
    DECLARE @xmlBody xml;
    DECLARE @Msgid int;
    DECLARE @ChannelType varchar(30);
    DECLARE @JobUrl varchar(50);
    DECLARE @LocalPath varchar(100);
    SET TEXTSIZE 2147483647;

    WHILE (1 = 1)
         BEGIN
             BEGIN TRANSACTION;
             WAITFOR(
             RECEIVE TOP (1) @RecvReqDlgHandle = conversation_handle,@RecvReqMsg = message_body,@RecvReqMsgName = message_type_name
                             FROM MessageQueue),TIMEOUT 5000;
             IF (@@ROWCOUNT = 0)
                 BEGIN
                     ROLLBACK;
                     BREAK;
                 END
             IF @RecvReqMsgName = N'AltovaWebRequests'
                 BEGIN
                    select @xmlBody = CAST(@RecvReqMsg as xml);
                    select @Msgid = @xmlBody.value('(//WebRequest/Msgid)[1]','int');
                    select @ChannelType = @xmlBody.value('(//WebRequest/ChannelType)[1]','varchar(30)');
                    select @FlowForceJobUrl = @xmlBody.value('(//WebRequest/JobUrl)[1]','varchar(50)');
                    select @LocalPath = @xmlBody.value('(//WebRequest/LocalPath)[1]','varchar(100)');
                    -- The following command always works fine
                    insert into ResultTable (Msgid,ChannelType,FlowForceJobUrl,LocalPath,[Conversation],DateTimeInserted) 
                        values (@Msgid,@ChannelType,@FlowForceJobUrl,@LocalPath,@RecvReqDlgHandle,getdate())
                    -- It stops functioning when I call the webservice
                    exec [spLaunchWebService_Test] @Msgid,@JobUrl,@LocalPath
                 END
             ELSE
                 IF @RecvReqMsgName = N'<a class="linkclass" href="http://schemas.microsoft.com/sql/Servicebroker/EndDialog">http://schemas.microsoft.com/sql/Servicebroker/EndDialog</a>'
                     BEGIN
                         END CONVERSATION @RecvReqDlgHandle;
                     END
                 ELSE
                     IF @RecvReqMsgName = N'<a class="linkclass" href="http://schemas.microsoft.com/sql/Servicebroker/Error">http://schemas.microsoft.com/sql/Servicebroker/Error</a>'
                         BEGIN
                             END CONVERSATION @RecvReqDlgHandle;
                         END
             COMMIT TRANSACTION;
         END
END

The procedure spLaunchWebService_Test sets several parameters and calls a webservice
The Stored Procedure for calling a webservice can also be easily found online but I use this one :


ALTER PROCEDURE [dbo].[spHTTPRequest]
    @URI varchar(2000) = 'http://000.000.000.000/service/',@methodName varchar(50) = 'Get',@requestBody varchar(8000) = '',@SoapAction varchar(255),@UserName nvarchar(100),-- Domain\UserName or UserName
    @Password nvarchar(100),@responseText varchar(8000) output
as
SET NOCOUNT ON
IF @methodName = ''
BEGIN
    select FailPoint = 'Method Name must be set'
    return
END
set @responseText = 'Failed'
DECLARE @objectID int
DECLARE @hResult int
DECLARE @source varchar(255),@desc varchar(255)
EXEC @hResult = sp_OACreate 'MSXML2.ServerXMLHTTP',@objectID OUT
IF @hResult <> 0
BEGIN
    EXEC sp_OAGetErrorInfo @objectID,@source OUT,@desc OUT
    SELECT hResult = @hResult,description = @desc,MedthodName = @methodName
    goto destroy
    return
END
-- open the destination URI with Specified method
EXEC @hResult = sp_OAMethod @objectID,'open',null,@methodName,@URI,'false',@UserName,@Password
IF @hResult <> 0
BEGIN
      EXEC sp_OAGetErrorInfo @objectID,@desc OUT
      SELECT     hResult = @hResult,MedthodName = @methodName
      goto destroy
      return
END
-- set request headers
EXEC @hResult = sp_OAMethod @objectID,'setRequestHeader','Content-Type','text/xml;charset=UTF-8'
IF @hResult <> 0
BEGIN
      EXEC sp_OAGetErrorInfo @objectID,@desc OUT
      SELECT      hResult = @hResult,MedthodName = @methodName
      goto destroy
      return
END
-- set soap action
EXEC @hResult = sp_OAMethod @objectID,'SOAPAction',@SoapAction
IF @hResult <> 0
BEGIN
      EXEC sp_OAGetErrorInfo @objectID,MedthodName = @methodName
      goto destroy
      return
END
declare @len int
set @len = len(@requestBody)
EXEC @hResult = sp_OAMethod @objectID,'Content-Length',@len
IF @hResult <> 0
BEGIN
      EXEC sp_OAGetErrorInfo @objectID,MedthodName = @methodName
      goto destroy
      return
END

-- send the request
EXEC @hResult = sp_OAMethod @objectID,'send',@requestBody
IF    @hResult <> 0
BEGIN
      EXEC sp_OAGetErrorInfo @objectID,MedthodName = @methodName
      goto destroy
      return
END
declare @statusText varchar(1000),@status varchar(1000)
-- Get status text
exec sp_OAGetProperty @objectID,'StatusText',@statusText out
exec sp_OAGetProperty @objectID,'Status',@status out
select @status,@statusText,@methodName
-- Get response text
exec sp_OAGetProperty @objectID,'responseText',@responseText out
IF @hResult <> 0
BEGIN
      EXEC sp_OAGetErrorInfo @objectID,MedthodName = @methodName
      goto destroy
      return
END
destroy:
      exec sp_OADestroy @objectID
SET NOCOUNT OFF

感谢并致以最诚挚的问候,

解决方法

看来我们的问题已经解决了; 如果 servicebroker 正在运行,必须在数据库中设置“SET TRUSTWORTHY ON”。