MySQL Schema 自動建表設計

整理以 C# Class 維護欄位型別、索引與描述,並於啟動時自動產生 MySQL Table 的設計計畫。

返回 docs

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_executionsTaskExecutionRecord保存任務層級執行狀態
node_executionsNodeExecutionRecord保存節點層級執行歷程
command_executionsCommandExecutionRecord保存設備命令執行結果
task_errorsTaskErrorRecord保存任務、節點或命令錯誤快照

第一版不處理報表、多案場、權限、設備主檔管理、自動資料搬移、自動刪除欄位或自動修改既有欄位型別。

建議模組切分

模組建議位置責任
Schema AttributeHS.DeviceControl.Infrastructure 或未來 DB 子模組描述 Table、Column、Index
Schema ModelInfrastructure 內部 model將 Attribute 解析成中立 schema
MySQL DDL GeneratorInfrastructure DB 實作將 schema 產成 MySQL 5.6.2 相容 SQL
Schema InitializerInfrastructure DB 實作啟動時檢查並建立缺少的 Table / Column / Index
TaskStoreInfrastructure DB 實作寫入與查詢任務歷程

Core 不應依賴這些模組。

C# Attribute 規格

DbTableAttribute

欄位型別說明
NamestringMySQL table 名稱
DescriptionstringTable COMMENT
Enginestring預設 InnoDB
Charsetstring預設 utf8

DbColumnAttribute

欄位型別說明
NamestringMySQL column 名稱
DbTypestringMySQL 欄位型別,例如 varchar(64)
IsRequiredbool是否 NOT NULL
IsPrimaryKeybool是否主鍵
DefaultValueSqlstring預設值 SQL,例如 CURRENT_TIMESTAMP
DescriptionstringColumn COMMENT

DbIndexAttribute

欄位型別說明
NamestringIndex 名稱
Columnsstring[]索引欄位清單
IsUniquebool是否唯一索引

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='任務執行紀錄';

啟動流程設計

  1. 讀取 appsettings 或環境變數中的 MySQL 連線設定。
  2. 檢查是否啟用 AutoCreateSchema
  3. 掃描已註冊的 schema record class。
  4. 將 Attribute 轉成中立 SchemaDefinition。
  5. 連線到既有 database。
  6. 讀取 information_schema 中的既有 table / column / index。
  7. 若 table 不存在,執行 CREATE TABLE IF NOT EXISTS
  8. 若 table 存在但缺少欄位,執行 ALTER TABLE ADD COLUMN
  9. 若缺少索引,執行 ALTER TABLE ADD INDEX
  10. 若欄位型別不同,只記錄錯誤或警告,不自動修改。

設定檔建議

{
  "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 初稿確認」,先確認 TaskExecutionRecordNodeExecutionRecordCommandExecutionRecordTaskErrorRecord 四個 Class 的欄位、型別、索引與描述是否符合需求。

在這份 Class 初稿確認前,不建議直接進入程式 repo 實作自動建表。