---
# System prepended metadata

title: 使用 BeeNET 進行資料存取：DbAccess、DbCommandHelper 與 SysDb
tags: [DbAccess, Database, Bee.NET]

---

# 如何用 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)
