процедура из БОЛ
CREATE PROCEDURE ProcessExpenseReport
AS
BEGIN
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION ;
DECLARE @conversationHandle UNIQUEIDENTIFIER ;
DECLARE @messageBody VARBINARY(MAX) ;
DECLARE @messageTypeName NVARCHAR(256) ;
SAVE TRANSACTION UndoReceive ;
WAITFOR (
RECEIVE TOP(1)
@messageTypeName = message_type_name,
@messageBody = message_body,
@conversationHandle = conversation_handle
FROM ExpenseQueue
), TIMEOUT 500 ;
IF @@ROWCOUNT = 0
BEGIN
ROLLBACK TRANSACTION ;
BREAK ;
END ;
-- Typical message processing loop: dispatch to a stored
-- procedure based on the message type name. End conversation
-- with an error for unknown message types.
-- Process expense report messages. If processing fails,
-- roll back to the save point and track the failed message.
IF (@messageTypeName =
'//Adventure-Works.com/AccountsPayable/ExpenseReport')
BEGIN
DECLARE @expenseReport NVARCHAR(MAX) ;
SET @expenseReport = CAST(@messageBody AS NVARCHAR(MAX)) ;
EXEC AdventureWorks.dbo.AddExpenseReport
@report = @expenseReport ;
IF @@ERROR <> 0
BEGIN
ROLLBACK TRANSACTION UndoReceive ;
EXEC TrackMessage @conversationHandle ;
END ;
ELSE
BEGIN
EXEC AdventureWorks.dbo.ClearMessageTracking
@conversationHandle ;
END ;
END ;
ELSE
-- For error messages and end dialog messages, end the
-- conversation.
IF (@messageTypeName =
'http://schemas.microsoft.com/SQL/ServiceBroker/Error' OR
@messageTypeName =
'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
BEGIN
END CONVERSATION @conversationHandle ;
EXEC dbo.ClearMessageTracking @conversationHandle ;
END ;
COMMIT TRANSACTION ;
END ;
END ;
хочу сделать так, чтобы в случае плохого сообщения оно все равно забиралось из очереди, чтобы действия процедур-обработчиков откатывались, но чтобы можно ыбло сделать записи в таблицах-логах.
Что если сделать так:
CREATE PROCEDURE ProcessExpenseReport
AS
BEGIN
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION ;
DECLARE @conversationHandle UNIQUEIDENTIFIER ;
DECLARE @messageBody VARBINARY(MAX) ;
DECLARE @messageTypeName NVARCHAR(256) ;
------------------ [i]SAVE TRANSACTION UndoReceive ;[/i]
WAITFOR (
RECEIVE TOP(1)
@messageTypeName = message_type_name,
@messageBody = message_body,
@conversationHandle = conversation_handle
FROM ExpenseQueue
), TIMEOUT 500 ;
IF @@ROWCOUNT = 0
BEGIN
ROLLBACK TRANSACTION ;
BREAK ;
END ;
[b] SAVE TRANSACTION UndoReceive ;[/b]
-- Typical message processing loop: dispatch to a stored
-- procedure based on the message type name. End conversation
-- with an error for unknown message types.
-- Process expense report messages. If processing fails,
-- roll back to the save point and track the failed message.
IF (@messageTypeName =
'//Adventure-Works.com/AccountsPayable/ExpenseReport')
BEGIN
DECLARE @expenseReport NVARCHAR(MAX) ;
SET @expenseReport = CAST(@messageBody AS NVARCHAR(MAX)) ;
EXEC AdventureWorks.dbo.AddExpenseReport
@report = @expenseReport ;
IF @@ERROR <> 0
BEGIN
ROLLBACK TRANSACTION UndoReceive ;
EXEC TrackMessage @conversationHandle ;
END ;
ELSE
BEGIN
EXEC AdventureWorks.dbo.ClearMessageTracking
@conversationHandle ;
END ;
END ;
ELSE
-- For error messages and end dialog messages, end the
-- conversation.
IF (@messageTypeName =
'http://schemas.microsoft.com/SQL/ServiceBroker/Error' OR
@messageTypeName =
'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
BEGIN
END CONVERSATION @conversationHandle ;
EXEC dbo.ClearMessageTracking @conversationHandle ;
END ;
COMMIT TRANSACTION ;
END ;
END ;