Similar a la sugerencia de @ David de poner los datos en una tabla de "progreso", pero sin necesidad de meterse con problemas de limpieza o concurrencia / separación de procesos:
- Cree uno nuevo
Guid
dentro del código de la aplicación y páselo como parámetro al Procedimiento almacenado. Almacene este Guid en una variable, ya que se usará varias veces.
- En el Procedimiento almacenado, cree una Tabla temporal global utilizando esa Guía como parte del nombre de la tabla, algo así
CREATE TABLE ##MyProcess_{GuidFromApp};
. La tabla puede tener las columnas de cualquier tipo de datos que necesite.
Siempre que tenga los datos, insértelos en esa tabla de temperatura global.
En el código de la aplicación, iniciar intentar leer los datos, pero envolver el SELECT
de una IF EXISTS
manera que no se producirá un error si la tabla no se ha creado todavía:
IF (OBJECT_ID('tempdb..[##MyProcess_{0}]')
IS NOT NULL)
BEGIN
SELECT * FROM [##MyProcess_{0}];
END;
Con String.Format()
, puede reemplazar {0}
con el valor en la variable Guid. Verifique si Reader.HasRows
es verdadero, luego lea los resultados, de lo contrario llame Thread.Sleep()
o lo que sea para luego sondear nuevamente.
Beneficios:
- Esta tabla está aislada de otros procesos, ya que solo el código de la aplicación conoce el valor Guid específico, por lo tanto, no es necesario preocuparse por otros procesos. Otro proceso tendrá su propia tabla temporal global privada.
- Debido a que es una tabla, todo está fuertemente tipado.
- Debido a que es una tabla temporal, cuando finaliza la sesión que ejecuta el Procedimiento almacenado, la tabla se limpiará automáticamente.
- Porque es una tabla temporal global :
- es accesible por otras sesiones, como una mesa permanente
- sobrevivirá al final del subproceso en el que se crea (es decir, la llamada
EXEC
/ sp_executesql
)
He probado esto y funciona como se esperaba. Puede probarlo usted mismo con el siguiente código de ejemplo.
En una pestaña de consulta, ejecute lo siguiente y luego resalte las 3 líneas en el comentario de bloque y ejecútelo:
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;
*/
Vaya a la pestaña "Mensajes" y copie el GUID que se imprimió. Luego, abra otra pestaña de consulta y ejecute lo siguiente, colocando el GUID que copió de la pestaña Mensajes de la otra sesión en la inicialización de variables en la línea 1:
DECLARE @TempTableID NVARCHAR(50) = N'GUID-from-other-session';
EXEC (N'SELECT * FROM [##MyProcess_' + @TempTableID + N']');
Sigue golpeando F5. Debería ver 1 entrada durante los primeros 10 segundos y luego 2 entradas durante los próximos 10 segundos.