將業務規則存放在資料庫 (預存程序) 還是應用層?無標準答案。但若選擇資料庫端,**業務規則鏈** 提供彈性:規則順序、啟用/停用、新增/移除皆透過資料表中繼資料控制,**無需修改程式碼、重新編譯、重新部署**。
CREATE TABLE dbo.BusinessLogic (
ProcessType varchar(20) NOT NULL, -- 業務流程類型 (如 CustomerOrders)
RunSequence tinyint NOT NULL, -- 執行順序
LogicProcedure varchar(255) NOT NULL, -- 預存程序名稱
BusinessLogicActive bit DEFAULT(1) NOT NULL, -- 是否啟用
CONSTRAINT PK_BusinessLogic PRIMARY KEY (ProcessType, RunSequence)
);
INSERT INTO dbo.BusinessLogic (ProcessType, RunSequence, LogicProcedure) VALUES
('CustomerOrders', 1, 'usp_Rule1_CheckCredit'),
('CustomerOrders', 2, 'usp_Rule2_ValidateInventory'),
('CustomerOrders', 3, 'usp_Rule3_CalculateDiscount'),
('CustomerOrders', 4, 'usp_Rule4_LogAudit');
CREATE PROCEDURE usp_Rule1_CheckCredit @RunSequence tinyint AS
BEGIN
PRINT 'Executing: ' + OBJECT_NAME(@@PROCID) + ' Seq=' + CAST(@RunSequence AS varchar(3));
-- 實際業務邏輯:檢查信用額度、拋錯誤、寫入暫存表等
END;
-- usp_Rule2...4 結構相同
限制:所有規則程序**必須接受相同參數簽章** (此處 `@RunSequence`),以便動態呼叫。
CREATE PROCEDURE dbo.usp_ExecuteBusinessRules @ProcessType varchar(20) AS
BEGIN
SET NOCOUNT ON;
DECLARE @ProcName varchar(255), @Seq tinyint;
DECLARE cur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT LogicProcedure, RunSequence
FROM dbo.BusinessLogic
WHERE ProcessType = @ProcessType
AND BusinessLogicActive = 1
ORDER BY RunSequence;
OPEN cur;
FETCH NEXT FROM cur INTO @ProcName, @Seq;
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
-- 動態執行:參數傳遞序號
EXEC @ProcName @Seq;
END TRY
BEGIN CATCH
-- 記錄錯誤、決定是否中斷鏈
PRINT 'ERROR in ' + @ProcName + ': ' + ERROR_MESSAGE();
-- 可選:BREAK; 或紀錄後繼續
END CATCH
FETCH NEXT FROM cur INTO @ProcName, @Seq;
END
CLOSE cur; DEALLOCATE cur;
END;
| 優點 | 缺點/限制 |
|---|---|
| 規則順序/啟用狀態熱調整 (無需重新部署) | 所有規則參數簽章必須一致 (擴充性受限) |
| 新增規則 = 建立 SP + 插入一列 | 動態 SQL 難以靜態分析、IntelliSense 無支援 |
| 集中管理、易於稽核 | 錯誤處理/交易邊界較複雜 (每規則獨立交易? 整體交易?) |
| 可整合參數表 (RuleParams) 實現參數化 | 大量規則時游標效能較差,可改用 `WHILE` + `TOP 1` 或 CLR |
建立 `BusinessLogicParams (ProcessType, RunSequence, ParamName, ParamValue, ParamType)`,執行引擎動態建構參數陣列呼叫 `sp_executesql`,突破單一參數限制。
業務規則鏈是「資料驅動行為」的經典模式。適用於**規則變動頻繁、業務邏輯相對獨立、團隊偏好資料庫端封裝**的情境。若規則高度複雜、需豐富型別系統、單元測試覆蓋率要求高,應用層規則引擎 (如 .NET Rules Engine、Drools) 更適合。