il y a quelque temps, j'ai posé une question sur la manière de faire le démarrage de la boîte de dialogue et d'envoyer plus de flexibilité afin qu'elle puisse être intégrée à une procédure qui prend les paramètres de la part des variables sysname.
cependant, comme l'a mentionné Rusanu dans la réponse, cette même technique ne peut être utilisée pour la clause de la réception.
En fait, cela fonctionnera. La plupart des verbes SSB acceptent les paramètres pour les arguments (sauf le nom de la file d'attente pour recevoir, bien sûr). Les paramètres sont de type sysname ...
en fait, le côté envoi est fait et j'essaie maintenant de faire de la réception flexible de la même manière, quelque chose comme:
CREATE PROCEDURE QueueReceive
@myTargetQueue SYSNAME
@cg UNIQUEIDENTIFIER OUTPUT
@ch UNIQUEIDENTIFIER OUTPUT
@msg XML OUTPUT
as
BEGIN TRANSACTION;
WAITFOR
( RECEIVE TOP(1)
@cg = conversation_group_id,
@msg = cast(message_body as XML),
@ch= conversation_handle
FROM @myTargetQueue
), TIMEOUT 3000;
COMMIT
...
Il semble que des variables de type sysname ne puissent être utilisées dans la clause de la réception? Si je dois le faire dans Dynamic SQL, comment puis-je retourner toutes les variables, conversation_group_id, conversation_handle, etc. de l'exécution SQL dynamique d'une fonction de réception? Y a-t-il une technique de performance meilleure pour accomplir la même chose?
Merci.
Correction/mise à jour SO FAR: Je crée un tas de clauses en fonction de ce que le paramètre transmis est, il n'exécutera simplement pas une autre déclaration de réception. Ce n'est pas efficace parce que je dois changer Code de procédure Chaque fois que j'ajoute une nouvelle file d'attente, mais je suppose que cela fera pour l'instant ...
Parce que la réception est fondamentalement une suppression et, en tant que telle, un plan de requête doit obéir aux mêmes restrictions SELECT/INSERT/SUPPRIMER/SUPPRIMER/UPDATE Les instructions ont, en particulier les restrictions que l'objet qu'il agit doit être connue sur Compiler temps, pas au temps d'exécution.
La seule option consiste à utiliser SQL dynamique, avec toutes les bénédictions et pièges qui suivent .
Vous pouvez aussi générer L'organisme de procédure lors du déploiement de projet, disposez d'un seul modèle et générer une procédure spécifique pour chaque file d'attente, spécialisée pour le nom de la file d'attente spécifique. Que cela soit réalisable dépend de nombreux facteurs, avant tout sur l'organisation de votre projet et de la manière dont vous déployez.
Sur une note latérale, je suis surpris d'entendre que vous avez de nombreuses files d'attente. En général, la tendance est d'avoir une file d'attente unique et plusieurs lecteurs de file d'attente ( activées procédures). Étant donné que la programmation SSB est entraînée par l'événement (attente pour le message, le message de processus, attendez le message, le message de processus, attendez un message ...) Avoir plus d'une file d'attente pour attendre que les messages ne deviennent plus difficiles, car l'application doit maintenant attendre sur plusieurs sources (par exemple, un fil par file d'attente au moins). Même avec l'activation du SSB, qui atténue la nécessité d'attendre explicite la méchanceté, il lance le code pour traiter le message à la demande, plusieurs files d'attente sont plus difficiles à gérer (max_Queue_readers par file d'attente ajoute peut-être trop de procédures activées internes lancées). Pensez à utiliser un seul service et une file d'attente sur le côté de la réception. Même lorsque plusieurs services sont nécessaires (pour une raison quelconque), ils peuvent être consolidés sur une file d'attente unique.
Il s'agit d'une procédure de réception de l'échantillon de travail qui est réutilisable sur différentes files d'attente.
ALTER PROCEDURE [dbo].[zBroker_OnReceive_WFItemsUpdated_Queue]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @h UNIQUEIDENTIFIER;
DECLARE @messageType int;
DECLARE @Packet VARCHAR(50);
DECLARE @MyId UNIQUEIDENTIFIER;
DECLARE @QueueName NVARCHAR(200);
DECLARE @Sql NVARCHAR(2000);
SET @MyId = NEWID(); -- Just an Id for testing that get's written to the log table
SET @QueueName = (
SELECT q.NAME
FROM
sys.service_queues q (nolock)
JOIN
sys.dm_broker_activated_tasks t (nolock) ON t.spid = @@SPID AND q.object_id = t.queue_id
)
SET @Sql = 'WAITFOR( RECEIVE TOP(1)
@h = conversation_handle,
@messageType = message_type_id,
@Packet = message_body
FROM ' + @QueueName + '), TIMEOUT 1000;'
--Clear the queue
WHILE (1=1)
BEGIN
BEGIN TRANSACTION;
EXECUTE sp_executesql @Sql
,N'@h UNIQUEIDENTIFIER OUTPUT,@messageType int OUTPUT,@Packet VARCHAR(50) OUTPUT'
,@h = @h OUTPUT
,@messageType = @messageType OUTPUT
,@Packet = @Packet OUTPUT
IF (@@ROWCOUNT = 0)
BEGIN
COMMIT;
BREAK;
END
ELSE
BEGIN
IF @messageType <= 2
BEGIN
END CONVERSATION @h;
END
ELSE
BEGIN
INSERT INTO t_log (logdata,msgdata,ProcId,StartTime)
VALUES ( @QueueName, @Packet ,@MyId,GETDATE());
WAITFOR DELAY '00:00:10';
UPDATE t_log SET EndTime = GETDATE()
WHERE logid = @@identity
END CONVERSATION @h;
END
COMMIT;
END
END
END