# 如何用 BeeNET 簡化資料存取?認識 DbAccess、DbCommandHelper、SysDb ![dbaccess](https://hackmd.io/_uploads/H1YEz1ftxe.png) > 在企業系統中,資料存取程式碼常常出現混亂、重複或資源釋放不當的問題。 > BeeNET 將「命令組裝」、「連線管理」、「靜態入口」清楚分工,讓開發人員能以一致且安全的方式進行資料操作。 > 本文帶你快速掌握三個核心組件:`DbAccess`、`DbCommandHelper`、`SysDb`,並學會最佳實務。 - NuGet:<https://www.nuget.org/packages/Bee.Db> - GitHub:<https://github.com/jeff377/bee-library> --- ## 1️⃣ 三者的定位 | 類別 | 功能定位 | 使用情境 | |---------------------|----------------|----------| | **DbAccess** | 資料庫存取物件 | 管理連線、執行 SQL 命令(支援同步/非同步),負責連線生命週期 | | **DbCommandHelper** | 命令組裝輔助 | 建立 `DbCommand`,處理參數符號、識別字跳脫、加入參數 | | **SysDb** | 靜態入口 | 對外提供最簡單的 API,透過 `databaseId` 自動定位資料庫並執行命令 | ### 🔗 三者關係示意圖 ```mermaid flowchart LR C[Caller] subgraph Helper[DbCommandHelper] H1[Build SQL/Parameters] H2[Create DbCommand] end S[SysDb] D[DbAccess] DB[(Database)] %% SQL string path C -->|SQL string| S %% DbCommand path C -->|DbCommand| S C --> H1 --> H2 --> C %% SysDb execution S --> D --> DB ``` 👉 無論是直接使用 SQL 字串,或透過 `DbCommandHelper` 組裝出 `DbCommand`,最後都會透過 `SysDb` 統一進入 `DbAccess` 執行。 --- ## 2️⃣ 各自的角色 ### 1. DbAccess —— 執行者 - 建立與開啟連線(含非同步)。 - 套用全域的命令逾時設定 (`BackendInfo.MaxDbCommandTimeout`)。 - 提供常見的資料存取方法: - `ExecuteNonQuery` - `ExecuteScalar` - `ExecuteReader` - `ExecuteDataTable` - `Query<T>`(物件映射,支援同步與非同步串流) 👉 **適合場景**:需要細部控制,或想要直接管理命令物件與執行過程。 --- ### 2. DbCommandHelper —— 組裝者 - 根據不同資料庫(SQL Server / MySQL / Oracle / SQLite)自動選擇參數符號(`@`、`:`)。 - 提供 `QuoteIdentifier()` 方法,自動套用資料庫識別字跳脫。 - 提供 `AddParameter()` 方法,簡化參數新增與型別設定。 👉 **適合場景**:需要產生具參數化的 SQL,或處理跨資料庫相容性。 --- ### 3. SysDb —— 快速入口 - 對外暴露靜態方法,例如: ```csharp int rows = SysDb.ExecuteNonQuery("common", "DELETE FROM Users WHERE Id = 1"); var table = SysDb.ExecuteDataTable("common", "SELECT * FROM Users"); ``` - 內部會自動找到對應的 `DatabaseItem`,建立 `DbAccess` 執行。 - **Dispose 規則**: - 使用字串 SQL → `SysDb` 內部自動釋放命令。 - 使用 `DbCommand` → 呼叫端需自行釋放命令。 👉 **適合場景**:需要快速呼叫資料庫,不必關心連線或命令管理。 --- ## 3️⃣ 使用範例 ### 快速查詢 ```csharp // 查詢筆數 int total = Convert.ToInt32( SysDb.ExecuteScalar("common", "SELECT COUNT(*) FROM Users")); ``` ### 帶參數的命令 ```csharp var helper = new DbCommandHelper(DatabaseType.SQLServer); helper.SetCommandText("SELECT * FROM [Users] WHERE [Role] = @role"); helper.AddParameter("role", FieldDbType.String, "Admin"); using (var cmd = helper.DbCommand) { var table = SysDb.ExecuteDataTable("common", cmd); } ``` ### 非同步查詢(.NET 8+ 串流) ```csharp await foreach (var user in SysDb.QueryStreamAsync<User>( "common", "SELECT Id, Name FROM Users")) { Console.WriteLine($"{user.Id}: {user.Name}"); } ``` ### 其他 Async 方法 BeeNET 也支援 `ExecuteNonQueryAsync`、`ExecuteScalarAsync`、`ExecuteReaderAsync` 等方法,適合用於: - 高併發的 Web API - 需要避免阻塞的長時間查詢 - 背景排程服務 --- ## 4️⃣ 開發人員注意事項 1. **命令釋放規則** - 使用字串 → `SysDb` 內部會釋放命令。 - 傳入 `DbCommand` → **自己負責 Dispose**。 2. **不要重複使用同一個 DbCommand** - 執行過的命令,可能會被資料庫驅動程式修改參數值或屬性。 - 最佳實務:**一次執行,一次建立**。 3. **記得關閉 Reader** - `ExecuteReader` 使用 `CommandBehavior.CloseConnection`。 - 只有在呼叫 `reader.Dispose()` 時,連線才會正確釋放。 --- ## 5️⃣ 總結 - `DbAccess`:控制連線與命令執行。 - `DbCommandHelper`:專注命令與參數組裝。 - `SysDb`:提供最簡單的靜態呼叫入口。 三者分工協作,讓 BeeNET 在資料存取上兼顧 **簡單性、彈性與穩健性**。 --- **📢 歡迎轉載,請註明出處** **📬 歡迎追蹤我的技術筆記與實戰經驗分享** [Facebook](https://www.facebook.com/profile.php?id=61574839666569) | [HackMD](https://hackmd.io/@jeff377) | [GitHub](https://github.com/jeff377) | [NuGet](https://www.nuget.org/profiles/jeff377)