Mirip dengan saran @ David untuk menempatkan data ke dalam tabel "progres", tetapi tanpa perlu dipusingkan dengan masalah pembersihan atau konkurensi / pemisahan proses:
- Buat yang baru
Guid
di dalam kode aplikasi dan berikan sebagai parameter ke Prosedur Tersimpan. Simpan Panduan ini dalam sebuah variabel karena akan digunakan beberapa kali.
- Dalam Prosedur Tersimpan, buat Tabel Sementara Global menggunakan Panduan itu sebagai bagian dari nama tabel, sesuatu seperti
CREATE TABLE ##MyProcess_{GuidFromApp};
. Tabel dapat memiliki kolom apa pun dari tipe data apa pun yang Anda butuhkan.
Kapan pun Anda memiliki data, masukkan ke dalam Tabel Temp Global itu.
Dalam kode aplikasi, mulai mencoba untuk membaca data, tetapi membungkus SELECT
dalam IF EXISTS
sehingga tidak akan gagal jika tabel belum dibuat belum:
IF (OBJECT_ID('tempdb..[##MyProcess_{0}]')
IS NOT NULL)
BEGIN
SELECT * FROM [##MyProcess_{0}];
END;
Dengan String.Format()
, Anda bisa mengganti {0}
dengan nilai dalam variabel Guid. Uji apakah Reader.HasRows
, dan jika benar maka bacalah hasilnya, panggil lagi Thread.Sleep()
atau apa saja untuk kemudian polling lagi.
Manfaat:
- Tabel ini diisolasi dari proses lain karena hanya kode aplikasi yang mengetahui nilai Guid spesifik, karenanya tidak perlu khawatir tentang proses lain. Proses lain akan memiliki tabel temp global pribadi sendiri.
- Karena ini adalah sebuah tabel, semuanya diketik dengan kuat.
- Karena ini adalah tabel sementara, ketika sesi yang menjalankan Prosedur Tersimpan berakhir, tabel tersebut akan dibersihkan secara otomatis.
- Karena ini adalah tabel sementara global :
- itu dapat diakses oleh Sesi lain, seperti meja permanen
- itu akan bertahan akhir dari sub-proses di mana ia dibuat (yaitu
EXEC
/ sp_executesql
panggilan)
Saya telah menguji ini dan berfungsi seperti yang diharapkan. Anda dapat mencobanya sendiri dengan contoh kode berikut.
Di satu tab permintaan, jalankan yang berikut, dan kemudian sorot 3 baris di blok-komentar dan jalankan itu:
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;
*/
Buka tab "Pesan" dan salin GUID yang dicetak. Kemudian, buka tab kueri lain dan jalankan yang berikut, letakkan GUID yang Anda salin dari tab Pesan Sesi lain ke inisialisasi variabel di baris 1:
DECLARE @TempTableID NVARCHAR(50) = N'GUID-from-other-session';
EXEC (N'SELECT * FROM [##MyProcess_' + @TempTableID + N']');
Terus memukul F5. Anda akan melihat 1 entri untuk 10 detik pertama, dan kemudian 2 entri untuk 10 detik berikutnya.