Ähnlich wie bei @ Davids Vorschlag, die Daten in eine "Fortschritts" -Tabelle zu stellen, ohne sich jedoch mit Aufräum- oder Parallelitäts- / Prozesstrennungsproblemen herumschlagen zu müssen:
- Erstellen Sie einen neuen
Guid
Code im App-Code und übergeben Sie ihn als Parameter an die gespeicherte Prozedur. Speichern Sie diese Guid in einer Variablen, da sie mehrmals verwendet wird.
- Erstellen Sie in der gespeicherten Prozedur eine globale temporäre Tabelle, indem Sie diese Guid als Teil des Tabellennamens verwenden
CREATE TABLE ##MyProcess_{GuidFromApp};
. Die Tabelle kann beliebige Spalten mit beliebigen Datentypen enthalten.
Wenn Sie die Daten haben, fügen Sie sie in diese globale Temp-Tabelle ein.
Versuchen Sie im App-Code, die Daten zu lesen, schließen Sie sie jedoch SELECT
ein, IF EXISTS
damit sie nicht fehlschlagen, wenn die Tabelle noch nicht erstellt wurde:
IF (OBJECT_ID('tempdb..[##MyProcess_{0}]')
IS NOT NULL)
BEGIN
SELECT * FROM [##MyProcess_{0}];
END;
Mit String.Format()
können Sie durch {0}
den Wert in der Guid-Variablen ersetzen . Testen Sie, ob Reader.HasRows
und ob true, lesen Sie die Ergebnisse, rufen Sie an Thread.Sleep()
oder was auch immer, um dann erneut abzufragen.
Leistungen:
- Diese Tabelle ist von anderen Prozessen isoliert, da nur der App-Code den spezifischen Guid-Wert kennt und Sie sich daher keine Gedanken über andere Prozesse machen müssen. Ein anderer Prozess verfügt über eine eigene private globale temporäre Tabelle.
- Da es sich um eine Tabelle handelt, ist alles stark typisiert.
- Da es sich um eine temporäre Tabelle handelt, wird die Tabelle beim Bereinigen der Sitzung, in der die gespeicherte Prozedur ausgeführt wird, automatisch bereinigt.
- Weil es sich um eine globale temporäre Tabelle handelt:
- Es ist für andere Sitzungen zugänglich, genau wie eine permanente Tabelle
- Es überlebt das Ende des Unterprozesses, in dem es erstellt wurde (dh der
EXEC
/ sp_executesql
-Anruf).
Ich habe dies getestet und es funktioniert wie erwartet. Sie können es mit dem folgenden Beispielcode selbst ausprobieren.
Führen Sie auf einer Abfrage-Registerkarte Folgendes aus, markieren Sie dann die 3 Zeilen im Blockkommentar und führen Sie Folgendes aus:
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;
*/
Gehen Sie zur Registerkarte "Nachrichten" und kopieren Sie die gedruckte GUID. Öffnen Sie dann eine andere Abfrage-Registerkarte und führen Sie die folgenden Schritte aus. Platzieren Sie die GUID, die Sie von der Registerkarte Nachrichten der anderen Sitzung kopiert haben, in die Variableninitialisierung in Zeile 1:
DECLARE @TempTableID NVARCHAR(50) = N'GUID-from-other-session';
EXEC (N'SELECT * FROM [##MyProcess_' + @TempTableID + N']');
Schlagen Sie weiter F5. Sie sollten 1 Eintrag für die ersten 10 Sekunden und dann 2 Einträge für die nächsten 10 Sekunden sehen.