# 用 DatabaseId 取代 Connection String:更安全、更靈活的資料庫存取方式

> Bee.Db 的 DbAccess 封裝常見的資料庫操作,最大特色是:以 DatabaseId 作為邏輯代碼來存取資料庫,取代傳統 Connection String 的方式。
- NuGet:<https://www.nuget.org/packages/Bee.Db>
- GitHub:<https://github.com/jeff377/bee-library>
---
## 1️⃣ 為什麼用 DatabaseId?
傳統做法把 **Connection String** 放在程式或設定檔,容易遇到:
- 🔑 **安全性風險**:密碼可能以明碼出現。
- 🔧 **維運成本高**:伺服器或帳密變更,要改多處。
- 🌀 **多資料庫混亂**:多家公司、年度分庫(如 `log_2025`、`log_2026`)或歷史庫時更複雜。
### 改用 **DatabaseId** 的優點
- 程式碼更簡潔、維護容易
- 資安更有保障(密碼加密 + 集中管理)
- 多資料庫與多租戶彈性(公司別、年度庫、同實體不同邏輯、SaaS 支援)
- 環境與部署更彈性(測試/正式切換、自動化工具整合)
- 效能最佳化與稽核監控(集中連線池、以 DatabaseId 追蹤使用狀況)
- 跨資料庫類型支援(SQLServer、PostgreSQL …)
### 以下是常見的 **DatabaseId** 命名與用途對應
| DatabaseId | 用途說明 |
|----------------|--------------------------------------------------------------------------|
| `common` | 共用資料庫 |
| `log` | 記錄與稽核資料庫(單一庫) |
| `log_2025` | 記錄與稽核資料庫(依年份切割,例如 `log_2025`、`log_2026` …) |
| `company` | 公司資料庫(多家公司時可為 `company01`、`company02` …) |
| `history` | 歷史資料庫 / 封存資料庫 |
---
## 2️⃣ DatabaseSettings.xml 設定與密碼加密
所有連線定義集中在 **DatabaseSettings.xml**:由 `DatabaseId` 對應到實體資料庫設定。
建議使用 [BeeSettingsEditor](https://github.com/jeff377/bee-library/releases/download/BeeSettingsEditor-v1.0.3/BeeSettingsEditor-v1.0.3.zip) 維護此檔案,可將 `Password` 自動加密。`DbName`、`UserID`、`Password` 支援變數,實際連線前以屬性值取代。
> **載入行為**:`DatabaseSettings.xml` 會被反序列化為 `DatabaseSettings` 物件並快取。長時間未使用或來源檔變更時,快取會釋放並重新載入。
**範例設定**:
```xml
<DatabaseItem Id="common"
DisplayName="Common Database"
DatabaseType="SQLServer"
ConnectionString="Data Source=.; Initial Catalog={@DbName}; Persist Security Info=True; User ID={@UserID}; Password={@Password}; TrustServerCertificate=True"
DbName="MyDb"
UserId="sa"
Password="enc:EAAAALOGDAAKhytCWFXqz...">
</DatabaseItem>
```
---
## 3️⃣ 初始化、建立方式與範例
### 初始化(一次性)
```csharp
// 設定定義路徑,即 DatabaseSettings.xml 所在目錄
BackendInfo.DefinePath = @"D:\DefinePath";
// 初始化金鑰,以解密 DatabaseSettings.xml 中的加密資料
var settings = CacheFunc.GetSystemSettings();
settings.BackendConfiguration.InitializeSecurityKeys();
// 若有引用 Bee.Business 組件,可改用:
// settings.Initialize();
// 註冊資料庫提供者
DbProviderManager.RegisterProvider(DatabaseType.SQLServer, Microsoft.Data.SqlClient.SqlClientFactory.Instance);
```
### 建立與使用
方式一:建立 DbAccess 物件
```csharp
var databaseItem = CacheFunc.GetDatabaseItem("common");
var dbAccess = new DbAccess(databaseItem);
dbAccess.ExecuteNonQuery("DELETE FROM Users WHERE Id = 1");
```
方式二:使用 SysDb(推薦)
```csharp
SysDb.ExecuteNonQuery("common", "DELETE FROM Users WHERE Id = 1");
```
### 常用存取方法
| 功能 | 方法名稱 | 範例程式碼 |
|--------------------|--------------------|------------|
| 查詢 DataTable | ExecuteDataTable | `var dt = SysDb.ExecuteDataTable("common", "SELECT * FROM Users");` |
| 執行增刪改 | ExecuteNonQuery | `int n = SysDb.ExecuteNonQuery("common", "DELETE FROM Users WHERE Id = 1");` |
| 取得單一值 | ExecuteScalar | `int total = (int)SysDb.ExecuteScalar("common", "SELECT COUNT(*) FROM Users");` |
| 逐筆讀取 | ExecuteReader | `var r = SysDb.ExecuteReader("common", "SELECT * FROM Users");` |
| 映射成強型別集合 | Query<T> | `var list = SysDb.Query<User>("common", "SELECT Id, Name FROM Users");` |
| 批次更新 DataTable | UpdateDataTable | `SysDb.UpdateDataTable("common", dt, insertCmd, updateCmd, deleteCmd);` |
| 測試連線 | TestConnection | `bool ok = SysDb.TestConnection("common");` |
---
## 4️⃣ 結語
用 DatabaseId 取代 Connection String,把「連線細節」從應用程式抽離到設定檔,帶來:
🔐 更高安全:密碼加密、不再在程式或設定檔明碼暴露。
🔄 更好維運:切換資料庫或變更密碼只改設定檔。
🧩 更適企業級:天生支援多公司、多年度、歷史/封存等複雜場景。
>透過 DatabaseId 抽象化設計,程式可以專注在商業邏輯,資料庫連線與管理則交由設定檔與框架處理,這就是 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)