Handling Service Broker ErrorsMarch 9, 2009 In the previous installment of our series dedicated to the most prominent
features of SQL Server 2005 Express Edition, we have been discussing the use of
transactions in protecting integrity and consistency of Service Broker-based
communication. As part of this discussion, we have presented a sample code
illustrating this concept, consisting of T-SQL statements which, when executed
on an initiator, started a conversation and sent a single message to a target
after storing its content in a local auxiliary table. All of these actions were
incorporated into a single transaction, which was either committed following
their successful completion, or rolled back if any of them failed. In our
example, we have leveraged the most basic form of As you might recall, we have implemented an internally activated stored
procedure
In our error checking routine, we will take this information into account,
deciding whether to force transaction rollback or invoke its commit based on
the value returned by
-- on srvEnt01
USE dbSBEnt01
GO
ALTER PROCEDURE dbo.cspProcessqRecv
WITH EXECUTE AS OWNER
AS
BEGIN
DECLARE @convHandle UNIQUEIDENTIFIER;
DECLARE @msgTypeName SYSNAME;
DECLARE @status TINYINT;
DECLARE @srvName NVARCHAR(512);
DECLARE @srvConName NVARCHAR(256);
DECLARE @msgTypeValidation AS NCHAR(2);
DECLARE @msgBody NVARCHAR(400);
DECLARE @cmd AS NVARCHAR(50);
DECLARE @errNum AS INTEGER;
DECLARE @errDesc AS NVARCHAR(400);
BEGIN TRY
BEGIN TRANSACTION;
WAITFOR(RECEIVE TOP(1)
@convHandle = conversation_handle,
@msgTypeName = message_type_name,
@status = status,
@srvName = service_name,
@srvConName = service_contract_name,
@msgTypeValidation = validation,
@msgBody = CAST(message_body AS NVARCHAR(400))
FROM qRecv),
TIMEOUT 1000;
IF(@@rowcount != 0)
BEGIN
INSERT INTO
tbMsgRecv(convHandle, msgTypeName, [status], srvName, srvConName, msgTypeValidation, msgBody)
VALUES(@convHandle, @msgTypeName, @status, @srvName, @srvConName, @msgTypeValidation, @msgbody);
END CONVERSATION @convHandle;
END
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
SET @errNum = ERROR_NUMBER();
SET @errDesc = ERROR_MESSAGE();
IF (XACT_STATE()) = -1
BEGIN
ROLLBACK TRANSACTION;
BEGIN TRANSACTION;
RECEIVE TOP(1)
@msgBody = CAST(message_body AS NVARCHAR(400))
FROM qRecv
WHERE conversation_handle = @convHandle;
SEND ON CONVERSATION @convHandle
MESSAGE TYPE [//databaseJournal.com/SQL2005EX/ServiceBroker/msgNV] (@msgBody)
END CONVERSATION @convHandle
WITH ERROR = @errNum DESCRIPTION = @errDesc;
COMMIT TRANSACTION;
END
IF (XACT_STATE()) = 1
BEGIN
INSERT INTO
tbMsgRecvErr(convHandle, msgTypeName, srvName, srvConName, msgTypeValidation, msgBody)
VALUES(@convHandle, @msgTypeName, @srvName, @srvConName, @msgTypeValidation, @msgBody);
END CONVERSATION @convHandle
WITH ERROR = @errNum DESCRIPTION = @errDesc;
COMMIT TRANSACTION;
END
END CATCH;
END
Under favorable circumstances, the code enclosed within the Clearly our example could be further refined and enhanced. For example, we should make sure that the initiator can properly react to each type of message returned by its target (and vice versa), including those generated by our code as well as by Service Broker. In absence of such provisions, you might have to rely on built-in Service Broker mechanism dealing with error conditions, known as Poison Message Detection, which we will describe in the next article of our series. |