web-dev-qa-db-fra.com

Comment faire un courtier de service flexible Recevez dans une procédure SQL stockée, comment transmettre le paramètre "de" dans Recevoir

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.

Procédure de courtier de service qui sera utilisée par plusieurs initiateurs pour commencer la conversation de la boîte de dialogue. Comment transmettre un paramètre à celui-ci

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 ...

4
fa1c0n3r

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.

5
Remus Rusanu

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
3
Andre Booysen