Аналогично предложению @ David для помещения данных в таблицу «прогресса», но без необходимости возиться с проблемами очистки или параллелизма / разделения процессов:
- Создайте новый
Guid
код приложения и передайте его в качестве параметра хранимой процедуре. Сохраните этот Guid в переменной, так как он будет использоваться несколько раз.
- В хранимой процедуре создайте глобальную временную таблицу, используя этот Guid как часть имени таблицы, что-то вроде
CREATE TABLE ##MyProcess_{GuidFromApp};
. Таблица может иметь любые столбцы с любыми типами данных, которые вам нужны.
Когда у вас есть данные, вставьте их в эту глобальную временную таблицу.
В коде приложения, начинают пытаться читать данные, но обернуть SELECT
в IF EXISTS
так что не будет ошибкой , если таблица не была создана еще:
IF (OBJECT_ID('tempdb..[##MyProcess_{0}]')
IS NOT NULL)
BEGIN
SELECT * FROM [##MyProcess_{0}];
END;
С String.Format()
, вы можете заменить {0}
на значение в переменной Guid. Проверьте, если Reader.HasRows
и если true, то прочитайте результаты, иначе позвоните Thread.Sleep()
или как угодно, чтобы потом опросить снова.
Льготы:
- Эта таблица изолирована от других процессов, поскольку только код приложения знает конкретное значение Guid, поэтому не нужно беспокоиться о других процессах. Другой процесс будет иметь свою собственную глобальную временную таблицу.
- Поскольку это таблица, все строго напечатано.
- Поскольку это временная таблица, по завершении сеанса, выполняющего хранимую процедуру, таблица будет очищена автоматически.
- Потому что это глобальная временная таблица:
- это доступно другим Сессиям, точно так же как постоянный стол
- он переживет окончание подпроцесса, в котором он создан (т.е. вызов
EXEC
/ sp_executesql
)
Я проверил это, и он работает как ожидалось. Вы можете попробовать это сами с помощью следующего примера кода.
На одной вкладке запроса выполните следующее, а затем выделите 3 строки в блок-комментарии и выполните это:
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;
*/
Перейдите на вкладку «Сообщения» и скопируйте напечатанный GUID. Затем откройте другую вкладку запроса и выполните следующую команду, поместив GUID, скопированный с вкладки «Сообщения другого сеанса», в инициализацию переменной в строке 1:
DECLARE @TempTableID NVARCHAR(50) = N'GUID-from-other-session';
EXEC (N'SELECT * FROM [##MyProcess_' + @TempTableID + N']');
Продолжай бить F5. Вы должны увидеть 1 запись в течение первых 10 секунд, а затем 2 записи в течение следующих 10 секунд.