Semblable à la suggestion de @ David de mettre les données dans un tableau de "progression", mais sans avoir à s'occuper des problèmes de nettoyage ou de concurrence / séparation des processus:
- Créez-en un nouveau
Guid
dans le code d'application et transmettez-le en tant que paramètre à la procédure stockée. Stockez ce Guid dans une variable car il sera utilisé plusieurs fois.
- Dans la procédure stockée, créez une table temporaire globale en utilisant ce Guid dans le nom de la table, quelque chose comme
CREATE TABLE ##MyProcess_{GuidFromApp};
. La table peut avoir toutes les colonnes de tous les types de données dont vous avez besoin.
Chaque fois que vous avez les données, insérez-les dans cette table de températures globales.
Dans le code de l'application, commencez à essayer de lire les données, mais encapsulez-le SELECT
dans un IF EXISTS
afin qu'il n'échoue pas si la table n'a pas encore été créée:
IF (OBJECT_ID('tempdb..[##MyProcess_{0}]')
IS NOT NULL)
BEGIN
SELECT * FROM [##MyProcess_{0}];
END;
Avec String.Format()
, vous pouvez remplacer {0}
par la valeur de la variable Guid. Testez si Reader.HasRows
et si vrai, lisez les résultats, sinon appelez Thread.Sleep()
ou quoi que ce soit pour interroger à nouveau.
Avantages:
- Cette table est isolée des autres processus car seul le code de l'application connaît la valeur Guid spécifique, donc pas besoin de se soucier des autres processus. Un autre processus aura sa propre table temporaire globale privée.
- Parce que c'est une table, tout est fortement typé.
- Puisqu'il s'agit d'une table temporaire, à la fin de la session exécutant la procédure stockée, la table sera nettoyée automatiquement.
- Parce que c'est une table temporaire globale :
- il est accessible par d'autres Sessions, tout comme une table permanente
- il survivra à la fin du sous-processus dans lequel il est créé (c'est-à-dire l' appel
EXEC
/sp_executesql
J'ai testé cela et cela fonctionne comme prévu. Vous pouvez l'essayer par vous-même avec l'exemple de code suivant.
Dans un onglet de requête, exécutez ce qui suit, puis mettez en surbrillance les 3 lignes dans le bloc-commentaire et exécutez cela:
CREATE
--ALTER
PROCEDURE #GetSomeInfoBackQuickly
(
@MessageTableName NVARCHAR(50) -- might not always be a GUID
)
AS
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX) = N'CREATE TABLE [##MyProcess_' + @MessageTableName
+ N'] (Message1 NVARCHAR(50), Message2 NVARCHAR(50), SomeNumber INT);';
-- Do some calculations
EXEC (@SQL);
SET @SQL = N'INSERT INTO [##MyProcess_' + @MessageTableName
+ N'] (Message1, Message2, SomeNumber) VALUES (@Msg1, @Msg2, @SomeNum);';
DECLARE @SomeNumber INT = CRYPT_GEN_RANDOM(2);
EXEC sp_executesql
@SQL,
N'@Msg1 NVARCHAR(50), @Msg2 NVARCHAR(50), @SomeNum INT',
@Msg1 = N'wow',
@Msg2 = N'yadda yadda yadda',
@SomeNum = @SomeNumber;
WAITFOR DELAY '00:00:10.000';
SET @SomeNumber = CRYPT_GEN_RANDOM(3);
EXEC sp_executesql
@SQL,
N'@Msg1 NVARCHAR(50), @Msg2 NVARCHAR(50), @SomeNum INT',
@Msg1 = N'wow',
@Msg2 = N'yadda yadda yadda',
@SomeNum = @SomeNumber;
WAITFOR DELAY '00:00:10.000';
GO
/*
DECLARE @TempTableID NVARCHAR(50) = NEWID();
RAISERROR('%s', 10, 1, @TempTableID) WITH NOWAIT;
EXEC #GetSomeInfoBackQuickly @TempTableID;
*/
Accédez à l'onglet "Messages" et copiez le GUID qui a été imprimé. Ensuite, ouvrez un autre onglet de requête et exécutez ce qui suit, en plaçant le GUID que vous avez copié à partir de l'onglet Messages de l'autre session dans l'initialisation variable sur la ligne 1:
DECLARE @TempTableID NVARCHAR(50) = N'GUID-from-other-session';
EXEC (N'SELECT * FROM [##MyProcess_' + @TempTableID + N']');
Continuez à frapper F5. Vous devriez voir 1 entrée pour les 10 premières secondes, puis 2 entrées pour les 10 secondes suivantes.