MySQL Schema 自動建表設計
本文件用於整理第二階段 MySQL TaskStore PoC 的 schema 維護方式。使用者希望 MySQL 的欄位型別、索引、描述可以直接在 C# Class 中維護,並且在 API 或 Host 啟動時自動產出 Table,不需要另外手動建置 MySQL Table。
本文件是設計計畫,不代表已經同意修改程式 repo、導入 WebApi、安裝套件、建立 schema 或變更專案啟動方式。
設計結論
C# Schema Definition + MySQL Schema Generator + Startup Schema Initializer
第一版不建議使用 EF Core Code First / Migration。原因是目前專案仍是 .NET 5.0,MySQL 版本為 5.6.2,第一版目標是 MySQL TaskStore PoC,不是完整 ORM 架構。手寫 DDL Generator 可明確控制欄位型別、索引、COMMENT、字元集與 InnoDB 設定。
適用範圍
| 資料表 | C# Class | 用途 |
|---|---|---|
task_executions | TaskExecutionRecord | 保存任務層級執行狀態 |
node_executions | NodeExecutionRecord | 保存節點層級執行歷程 |
command_executions | CommandExecutionRecord | 保存設備命令執行結果 |
task_errors | TaskErrorRecord | 保存任務、節點或命令錯誤快照 |
第一版不處理報表、多案場、權限、設備主檔管理、自動資料搬移、自動刪除欄位或自動修改既有欄位型別。
建議模組切分
| 模組 | 建議位置 | 責任 |
|---|---|---|
| Schema Attribute | HS.DeviceControl.Infrastructure 或未來 DB 子模組 | 描述 Table、Column、Index |
| Schema Model | Infrastructure 內部 model | 將 Attribute 解析成中立 schema |
| MySQL DDL Generator | Infrastructure DB 實作 | 將 schema 產成 MySQL 5.6.2 相容 SQL |
| Schema Initializer | Infrastructure DB 實作 | 啟動時檢查並建立缺少的 Table / Column / Index |
| TaskStore | Infrastructure DB 實作 | 寫入與查詢任務歷程 |
Core 不應依賴這些模組。
C# Attribute 規格
DbTableAttribute
| 欄位 | 型別 | 說明 |
|---|---|---|
Name | string | MySQL table 名稱 |
Description | string | Table COMMENT |
Engine | string | 預設 InnoDB |
Charset | string | 預設 utf8 |
DbColumnAttribute
| 欄位 | 型別 | 說明 |
|---|---|---|
Name | string | MySQL column 名稱 |
DbType | string | MySQL 欄位型別,例如 varchar(64) |
IsRequired | bool | 是否 NOT NULL |
IsPrimaryKey | bool | 是否主鍵 |
DefaultValueSql | string | 預設值 SQL,例如 CURRENT_TIMESTAMP |
Description | string | Column COMMENT |
DbIndexAttribute
| 欄位 | 型別 | 說明 |
|---|---|---|
Name | string | Index 名稱 |
Columns | string[] | 索引欄位清單 |
IsUnique | bool | 是否唯一索引 |
Class 維護範例
[DbTable("task_executions", Description = "任務執行紀錄")]
[DbIndex("idx_task_status", "status")]
[DbIndex("idx_task_started_at", "started_at")]
public class TaskExecutionRecord
{
[DbColumn("task_id", "varchar(64)", IsPrimaryKey = true, IsRequired = true, Description = "任務識別碼")]
public string TaskId { get; set; }
[DbColumn("workflow_id", "varchar(64)", IsRequired = true, Description = "Workflow 識別碼")]
public string WorkflowId { get; set; }
[DbColumn("status", "varchar(32)", IsRequired = true, Description = "任務狀態")]
public string Status { get; set; }
}
產出 SQL 範例
CREATE TABLE IF NOT EXISTS task_executions (
task_id varchar(64) NOT NULL COMMENT '任務識別碼',
workflow_id varchar(64) NOT NULL COMMENT 'Workflow 識別碼',
status varchar(32) NOT NULL COMMENT '任務狀態',
started_at datetime NULL COMMENT '開始時間',
ended_at datetime NULL COMMENT '結束時間',
PRIMARY KEY (task_id),
INDEX idx_task_status (status),
INDEX idx_task_started_at (started_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任務執行紀錄';
啟動流程設計
- 讀取 appsettings 或環境變數中的 MySQL 連線設定。
- 檢查是否啟用
AutoCreateSchema。 - 掃描已註冊的 schema record class。
- 將 Attribute 轉成中立 SchemaDefinition。
- 連線到既有 database。
- 讀取
information_schema中的既有 table / column / index。 - 若 table 不存在,執行
CREATE TABLE IF NOT EXISTS。 - 若 table 存在但缺少欄位,執行
ALTER TABLE ADD COLUMN。 - 若缺少索引,執行
ALTER TABLE ADD INDEX。 - 若欄位型別不同,只記錄錯誤或警告,不自動修改。
設定檔建議
{
"Database": {
"Provider": "MySql",
"ConnectionString": "Server=localhost;Database=hs_device_control;Uid=app;Pwd=***;",
"AutoCreateSchema": true,
"DryRunSchemaSql": false,
"StopOnSchemaMismatch": true
}
}
自動化允許與禁止規則
| 類型 | 第一版是否允許自動處理 | 原因 |
|---|---|---|
| Table 不存在 | 允許 | 可安全建立 |
| Column 不存在 | 允許 | 可安全補欄位 |
| Index 不存在 | 允許 | 可安全補索引 |
| Column COMMENT 不同 | 可先只警告 | 不影響資料正確性 |
| Column 型別不同 | 不允許自動修改 | 可能造成資料截斷 |
| Column 被移除 | 不允許自動刪除 | 避免破壞既有資料 |
| Database 不存在 | 第一版不建議自動建立 | 權限與部署責任需分清楚 |
驗證節點
| 驗證項目 | 預期結果 |
|---|---|
| 空 database 啟動 | 自動建立四張 TaskStore table |
| 重複啟動 | 不重複建立、不報錯 |
| 缺少欄位 | 自動補欄位 |
| 缺少索引 | 自動補索引 |
| 欄位型別不一致 | 回報 schema mismatch,不自動修改 |
| DryRun 模式 | 只輸出 SQL,不修改 DB |
| DB 權限不足 | 回傳明確錯誤與 Log |
建議下一步
MySQL schema Class 初稿請參考:MySQL schema Class 初稿。
建議下一步做「MySQL schema Class 初稿確認」,先確認 TaskExecutionRecord、NodeExecutionRecord、CommandExecutionRecord、TaskErrorRecord 四個 Class 的欄位、型別、索引與描述是否符合需求。
在這份 Class 初稿確認前,不建議直接進入程式 repo 實作自動建表。