Semelhante à sugestão de @ David de colocar os dados em uma tabela de "progresso", mas sem precisar mexer nos problemas de limpeza ou simultaneidade / separação de processos:
- Crie um novo
Guid
dentro do código do aplicativo e passe-o como um parâmetro para o Stored Procedure. Armazene este Guid em uma variável, pois ele será usado várias vezes.
- No procedimento armazenado, crie uma tabela temporária global usando esse guia como parte do nome da tabela, algo como
CREATE TABLE ##MyProcess_{GuidFromApp};
. A tabela pode ter quaisquer colunas dos tipos de dados que você precisa.
Sempre que você tiver os dados, insira-os na tabela Temp Global.
No código do aplicativo, comece a tentar ler os dados, mas envolva o SELECT
em um IF EXISTS
modo que não irá falhar se a tabela não foi criado ainda:
IF (OBJECT_ID('tempdb..[##MyProcess_{0}]')
IS NOT NULL)
BEGIN
SELECT * FROM [##MyProcess_{0}];
END;
Com String.Format()
, você pode substituir {0}
pelo valor na variável Guid. Teste se Reader.HasRows
, e se for verdadeiro, leia os resultados; caso contrário, ligue Thread.Sleep()
ou o que quer que seja para pesquisar novamente.
Benefícios:
- Esta tabela é isolada de outros processos, pois apenas o código do aplicativo conhece o valor específico do Guid, portanto, não é necessário se preocupar com outros processos. Outro processo terá sua própria tabela temporária global privada.
- Por ser uma tabela, tudo é fortemente digitado.
- Por ser uma tabela temporária, quando a sessão que executa o Procedimento Armazenado terminar, a tabela será limpa automaticamente.
- Porque é uma tabela temporária global :
- é acessível por outras sessões, assim como uma tabela permanente
- sobreviverá ao final do subprocesso em que é criado (ou seja, a chamada
EXEC
/ sp_executesql
)
Eu testei isso e funciona como esperado. Você pode tentar por si mesmo com o seguinte código de exemplo.
Em uma guia de consulta, execute o seguinte e destaque as 3 linhas no comentário do bloco e execute:
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;
*/
Vá para a guia "Mensagens" e copie o GUID que foi impresso. Em seguida, abra outra guia de consulta e execute o seguinte, colocando o GUID que você copiou da guia Mensagens da outra sessão na inicialização da variável na linha 1:
DECLARE @TempTableID NVARCHAR(50) = N'GUID-from-other-session';
EXEC (N'SELECT * FROM [##MyProcess_' + @TempTableID + N']');
Continue batendo F5. Você deverá ver 1 entrada pelos primeiros 10 segundos e depois 2 entradas pelos próximos 10 segundos.