架構困境:業務邏輯放哪裡?
SQL Server 提供豐富的 T-SQL (SP、Trigger、UDF) 可封裝業務邏輯。但**全置於資料庫**會導致:
- **擴展性瓶頸**:SP/Trigger 僅能操作本地資料,無法水平分庫分表;單機 CPU/記憶體上限硬性限制併發。
- **測試困難**:資料庫邏輯難以單元測試、Mock、CI/CD 整合。
- **語言表達力受限**:T-SQL 缺乏 OOP、設計模式、豐富庫生態,複雜演算法寫起來痛苦且難維護。
- **部署耦合**:資料庫升級/遷移需同步邏輯代碼,風險大。
分層架構決策矩陣
| 層級 | 職責 | 技術棧 | 操作模式 | 核心原則 |
| 資料存取層 | CRUD、集合查詢、批量操作、交易控制、安全邊界 | T-SQL (SP、View、UDF) | 集合操作 | 資料不出庫、集合在引擎端處理、最小化網路傳輸 |
| 業務邏輯層 | 複雜規則、流程編排、演算法、外部整合、單元測試 | .NET (C#/VB.NET) / Java / Python | 列/物件操作 | 彈性擴展、豐富生態、可測試、版本管理 |
| 表現層 | UI、API 序列化、權限檢查 | ASP.NET / WPF / React / Vue | 視圖模型 | 單一職責、解耦 |
何時用集合操作 (T-SQL)?
- 大量資料過濾、聚合、排序、分頁、JOIN。
- 批量 INSERT/UPDATE/DELETE (百萬行)。
- 交易一致性邊界 (ACID)。
- 安全邊界:資料列/欄位級權限、動態資料遮罩。
何時用列操作 (.NET)?
- 複雜業務規則引擎 (稅務計算、定價引擎、工作流)。
- 需大量 CPU 運算、記憶體緩存、遞迴演算法。
- 呼叫外部服務 (HTTP、gRPC、Message Queue)。
- 需單元測試、Mock、TDD。
游標陷阱:為什麼 T-SQL 不適合逐行處理
T-SQL `CURSOR` 是**昂貴物件**:記憶體開銷大、鎖持久、無法平行化、優化器難優化。**千萬行游標迴圈 = 效能災難**。正確做法:`SELECT` 取回結果集 → .NET 端 `foreach` / PLINQ / TPL Dataflow 處理 → 批量寫回。
最佳實踐:可重用資料存取框架
- 封裝 **通用 CRUD、動態查詢、分頁、批量操作、交易範本** 為基礎類庫 (或用 Dapper/EF Core/ADO.NET)。
- SP 僅暴露 **粗粒度、集合導向** 介面:`GetOrdersByFilter`、`BulkUpdateStatus`、`ExecuteMonthEndClosing`。
- 業務層組合 SP、協調交易、處理例外、發布事件。
結語
**資料庫做資料庫擅長的事 (集合、交易、安全),應用層做應用層擅長的事 (邏輯、運算、整合、測試)**。這不是非黑即白的二選一,而是**依據操作模式 (集合 vs 列) 劃分邊界**的架構智慧。避開「萬能 SP」反模式,擁抱分層,系統才能在規模增長時保持彈性與可維護性。