Sql-Server
通過 SQL 儲存過程創建 Hangfire 作業
我知道如何通過 .NET C# 程式碼創建 Hangfire 作業,但在某些情況下我希望數據庫觸發器執行 Hangfire 作業。我在網上搜尋但一無所獲,所以我嘗試編寫自己的儲存過程。
Hangfire 表位於 SQL Server 中,因此我假設我應該能夠通過將記錄插入正確的表來創建作業。
這不是一個簡單的過程,但我所做的是通過 C# 程式碼創建一個作業,研究 Hangfire 如何儲存數據,並編寫了一個儲存過程來完成同樣的事情。以下程式碼有效,但承認草率。
任何人都可以建議對此進行改進,或建議更好的儲存過程嗎?
-- ============================================= -- Author: Gary Jorgenson, RN | robintek.com -- Create date: 3/23/2021 -- Description: Create a Hangfire Job and Enqueue it -- ============================================= ALTER PROCEDURE [dbo].[core_sp_CreateHangFireJob] @type AS VARCHAR(150) = NULL , @Method AS VARCHAR(50) = NULL , @AppCode AS VARCHAR(50) = NULL , @Version AS VARCHAR(15) = NULL , @Culture AS VARCHAR(50) = NULL , @PublicKeyToken AS VARCHAR(50) = NULL , @ParameterTypes AS VARCHAR(250) = NULL , @Arguments AS VARCHAR(250) = NULL AS BEGIN DECLARE @RandomString AS VARCHAR(MAX) = LOWER(RIGHT(CAST(NEWID() AS NVARCHAR(MAX)),8)) -- Build the JSON string Hangfire wants DECLARE @InvocationData AS VARCHAR(2000) = '{"Type":"' + ISNULL(@type,'BackgroundJobs') + ', ' + 'App_Code.' + ISNULL(@AppCode, @RandomString) + ', ' + 'Version=' + ISNULL(@Version, '0.0.0.0') + ', ' + 'Culture=' + ISNULL(@Culture,'neutral') + ', ' + 'PublicKeyToken=' + ISNULL(@PublicKeyToken,'null') + '",' + '"Method":"' + ISNULL(@method,'UpdateActivityLog') + '","' + 'ParameterTypes":"' + ISNULL(@ParameterTypes,'[]') + '","' + 'Arguments":null}' -- For some reason, Hangfire seems to set the inserted date/time as 4 hours ahead of actual time DECLARE @inserted DATETIME = DATEADD(HOUR, 4, GETDATE()); -- Insert a record into Hangfire Job table. First of several inserts INSERT INTO [dbo].[Job] ( [StateName] , [InvocationData] , [Arguments] , [CreatedAt] ) VALUES ( 'Enqueued' , @InvocationData , '['+ ISNULL( '"' + @Arguments + '"','') + ']', @inserted ) -- Get the JobId as we'll need it for other inserts DECLARE @JobId AS BIGINT = IDENT_CURRENT('[dbo].[Job]'); -- Break out date and time separately as well need to build -- a JSON string formatted properly for Hangfire DECLARE @insertedDate AS DATE = CONVERT(DATE, @inserted); DECLARE @insertedTime AS TIME = CONVERT(VARCHAR(10), @inserted, 108) DECLARE @EnqueuedAt AS VARCHAR(2000) = '{"EnqueuedAt":"' + CONVERT(VARCHAR(20), @insertedDate) + 'T'+ CONVERT(VARCHAR(20), @insertedTime) + 'Z","Queue":"default"}' -- Insert record into Hanfire state table showing this job -- as Enqueued INSERT INTO [dbo].[State] ( [JobId] , [Name] , [Reason] , [CreatedAt] , [Data] ) VALUES ( @JobId , 'Enqueued', NULL , @inserted , @EnqueuedAt ) -- Retrieve the new StateId as we have to update the job record with current StateId DECLARE @StateId AS BIGINT = scope_identity(); UPDATE [dbo].[Job] SET StateId = @StateId WHERE id = @JobId -- Insert records into Hangfire JobParameter table showing the CurrentCulture INSERT INTO [dbo].[JobParameter] ( [JobId] , [Name] , [Value] ) VALUES ( @JobId , 'CurrentCulture' , '"en-US"' ) -- Insert record into Hangfire JobParameter table showing the CurrentUICulture INSERT INTO [dbo].[JobParameter] ( [JobId] , [Name] , [Value] ) VALUES ( @JobId , 'CurrentUICulture' , '"en-US"' ) -- Lastly, inserting the job Id into the Hangfire JobQueue table to start the job INSERT INTO [dbo].[JobQueue] ( [JobId] , [Queue] ) VALUES ( @JobId , -- JobId - bigint N'default' -- Queue - nvarchar(50) ) RETURN 1 END
Hangfire 是一個開源框架,可幫助您創建、處理和管理後台作業,即您不想放入請求處理管道的操作。
它已成為 Web 應用程序開發人員管理後台作業的流行工具。在大多數情況下,Hangfire 作業是在應用程式碼中創建或設置為重複任務。
我最初計劃在 Stack Overflow 上發布這個問題,因為開發人員更可能熟悉 Hangfire。有人建議我在這裡發布更多面向 SQL 的問題。
在 Hangfire 網站上,我找不到任何支持對 SQL 數據庫進行外部修改的參考資料。所以我認為它不受支持。
當您直接修改數據庫時,您將跳過應用程序中實現的所有記憶體和驗證層。它可能會導致應用程序不穩定並且很難調試。此外,數據庫架構可能會在產品更新時發生變化。
我會推薦不同的解決方案:
- 如果您需要快速觸發器和來自觸發器的半實時作業,請使用服務代理隊列。在觸發器中,您將創建一條消息,然後使用 C# 服務、SSIS 或正常 Windows 服務來響應消息並創建作業。
- 如果觸發器可能較慢,並且您希望在作業創建失敗時使觸發器失敗,請從觸發器(C# 儲存過程或 OLE)呼叫 Web API。
作為旁注,
DATEADD(HOUR, 4, GETDATE())
不適用於冬季,您需要AT TIME ZONE
在 SQL Server 中使用正確轉換為 UTC。