ServiceBroker :存储过程作为独立工作但不作为触发器
ServiceBroker : Stored procedure working as stand-alone but not as trigger
我们正在尝试从 SQL 服务器异步启动 Web 服务,而 Service Broker 似乎是最有趣的选择。
对于 Service Broker 本身,可以在网上找到许多不同的示例。我设法有一个工作示例,其中我在队列上的消息中发送了几个参数,并在消息到达时自动触发队列。
问题是当我将信息保存到另一个 table 时代码工作正常,但当我尝试调用网络服务时它失败了。然后它具有停止队列的效果。
当我 运行 存储过程本身但不是作为队列上的触发器时,它仍然有效。
请问有人知道我做错了什么吗?
我从队列中获取消息的存储过程如下:
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, @ChannelType, @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, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
-- set request headers
EXEC @hResult = sp_OAMethod @objectID, 'setRequestHeader', null, 'Content-Type', 'text/xml;charset=UTF-8'
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
-- set soap action
EXEC @hResult = sp_OAMethod @objectID, 'setRequestHeader', null, 'SOAPAction', @SoapAction
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
declare @len int
set @len = len(@requestBody)
EXEC @hResult = sp_OAMethod @objectID, 'setRequestHeader', null, 'Content-Length', @len
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
-- send the request
EXEC @hResult = sp_OAMethod @objectID, 'send', null, @requestBody
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
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, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
destroy:
exec sp_OADestroy @objectID
SET NOCOUNT OFF
谢谢并致以最诚挚的问候,
看来我们的问题已经解决了;
如果 servicebroker 是 运行.
,则必须在数据库中设置“SET TRUSTWORTHY ON”
我们正在尝试从 SQL 服务器异步启动 Web 服务,而 Service Broker 似乎是最有趣的选择。
对于 Service Broker 本身,可以在网上找到许多不同的示例。我设法有一个工作示例,其中我在队列上的消息中发送了几个参数,并在消息到达时自动触发队列。
问题是当我将信息保存到另一个 table 时代码工作正常,但当我尝试调用网络服务时它失败了。然后它具有停止队列的效果。
当我 运行 存储过程本身但不是作为队列上的触发器时,它仍然有效。
请问有人知道我做错了什么吗?
我从队列中获取消息的存储过程如下:
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, @ChannelType, @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, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
-- set request headers
EXEC @hResult = sp_OAMethod @objectID, 'setRequestHeader', null, 'Content-Type', 'text/xml;charset=UTF-8'
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
-- set soap action
EXEC @hResult = sp_OAMethod @objectID, 'setRequestHeader', null, 'SOAPAction', @SoapAction
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
declare @len int
set @len = len(@requestBody)
EXEC @hResult = sp_OAMethod @objectID, 'setRequestHeader', null, 'Content-Length', @len
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
-- send the request
EXEC @hResult = sp_OAMethod @objectID, 'send', null, @requestBody
IF @hResult <> 0
BEGIN
EXEC sp_OAGetErrorInfo @objectID, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
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, @source OUT, @desc OUT
SELECT hResult = @hResult,
description = @desc,
MedthodName = @methodName
goto destroy
return
END
destroy:
exec sp_OADestroy @objectID
SET NOCOUNT OFF
谢谢并致以最诚挚的问候,
看来我们的问题已经解决了; 如果 servicebroker 是 运行.
,则必须在数据库中设置“SET TRUSTWORTHY ON”