# 用抽象資料型別簡化 ERP 資料庫維護 > 跨資料庫支援 × 自動升級 × 一致性設計 ![field-dbtype-design](https://hackmd.io/_uploads/HJzaFqxJbl.png) ## 1️⃣ 緣起 在 ERP 系統中,資料表結構常隨著需求變動而頻繁調整,且往往需要同時支援 SQL Server/MySQL/PostgreSQL/Oracle 等多種資料庫。 若直接在程式中使用各資料庫的原生型別(如 `NVARCHAR`、`NUMBER` 等),一旦要異動欄位型別或調整長度,就必須修改所有 SQL 定義與程式碼,維護與遷移成本極高。 BeeNET 採用抽象資料型別(Abstract Data Type)的概念,以抽象的 `FieldDbType` 列舉來定義資料欄位,再由 **DbTable** 作為資料表結構定義物件。 部署時交由比對工具與命令產生器轉換為各資料庫對應的 DDL / DML 語法,達成跨資料庫支援與自動升級。 --- ## 2️⃣ 抽象資料型別的優點 - **防止選錯型別**:只需宣告 `String`、`Text`、`DateTime` 等直觀型別,由框架自動轉換。 - **降低全域修改風險**:例如改為全面支援 Unicode,只需更新型別對應表。 - **支援多資料庫**:SQL Server、MySQL、PostgreSQL、Oracle 等異質環境一套定義即可。 - **簡化設計**:開發人員不用關心 `varchar/nvarchar` 等差異。 - **提升效率**:有利於測試、驗證與程式碼產生。 --- ## 3️⃣ FieldDbType 列舉(抽象層) 抽象資料型別以列舉表示,統一由 **DbTable** 欄位的 `DbType` 屬性參照: ```csharp /// <summary> /// 欄位的抽象資料型別(跨資料庫對應)。 /// </summary> public enum FieldDbType { String, // 一般字串(具長度) Text, // 大量文字 Boolean, // 布林值 AutoIncrement, // 自動遞增整數(資料表主鍵常用) Short, // 16-bit 整數 Integer, // 32-bit 整數 Long, // 64-bit 整數 Decimal, // 十進位數值(高精度) Currency, // 金額(預設 19,4) Date, // 日期 DateTime, // 日期時間 Guid, // 全域唯一識別碼 Binary // 二進位資料 } ``` --- ## 4️⃣ FieldDbType 資料型別對應表 | FieldDbType | SQL Server | MySQL | PostgreSQL | Oracle | |---------------|----------------------------|---------------------------------|---------------------------------------------|------------------------| | String | NVARCHAR(n) | VARCHAR(n) | VARCHAR(n) | VARCHAR2(n) | | Text | NVARCHAR(MAX) | TEXT | TEXT | CLOB | | Boolean | BIT | TINYINT(1) / BOOLEAN | BOOLEAN | NUMBER(1) | | AutoIncrement | INT IDENTITY(1,1) | INT AUTO_INCREMENT | SERIAL / INT GENERATED ALWAYS AS IDENTITY | NUMBER + SEQUENCE | | Short | SMALLINT | SMALLINT | SMALLINT | NUMBER(5) | | Integer | INT | INT | INTEGER | NUMBER(10) | | Long | BIGINT | BIGINT | BIGINT | NUMBER(19) | | Decimal | DECIMAL(p,s) | DECIMAL(p,s) | NUMERIC(p,s) | NUMBER(p,s) | | Currency | DECIMAL(19,4) | DECIMAL(19,4) | NUMERIC(19,4) | NUMBER(19,4) | | Date | DATE | DATE | DATE | DATE | | DateTime | DATETIME | DATETIME | TIMESTAMP | TIMESTAMP | | Guid | UNIQUEIDENTIFIER | CHAR(36) / BINARY(16) | UUID | RAW(16) | | Binary | VARBINARY(MAX) | BLOB | BYTEA | BLOB | --- ## 5️⃣ BeeNET 元件協作流程 - **DbTable**:為資料表結構的定義來源;以 `FieldDbType` 宣告欄位結構與限制(長度、精度、是否必填)。 - **TableSchemaComparer**:比對 DbTable 與實際資料庫結構,找出需新增/修改的欄位與索引。 - **TableSchemaBuilder**:依目標資料庫 Provider 產出 DDL/DML(Create/Alter/Index/Default/Sequence 等)並執行升級。 範例:使用 TableSchemaBuilder 建立或更新資料表 ```csharp // 載入指定 tableName 的 DbTable 定義,執行資料結構比對與更新 var builder = new TableSchemaBuilder(databaseId); builder.Execute(dbName, tableName); ``` > 此機制可於部署階段自動比對結構並同步升級。 --- ## 6️⃣ DbTable 定義範例 DbTable 物件會序列化為 XML 格式,存放於專案中以供版本控制與部署使用。每個資料表的結構定義皆以 XML 檔({TableName}.DbTable.xml)保存,確保開發、測試與正式環境的結構自動保持一致。 以 [st_user](https://github.com/jeff377/bee-library/blob/main/samples/Define/DbTable/Common/st_user.DbTable.xml) 資料表為例,示範 **DbTable** 定義方式: ```xml <?xml version="1.0" encoding="utf-8"?> <DbTable DbName="common" TableName="st_user" DisplayName="用戶"> <Fields> <DbField FieldName="sys_no" Caption="流水號" DbType="AutoIncrement" /> <DbField FieldName="sys_rowid" Caption="唯一識別" DbType="Guid" /> <DbField FieldName="sys_id" Caption="用戶帳號" DbType="String" Length="20" /> <DbField FieldName="sys_name" Caption="用戶名稱" DbType="String" Length="20" /> <DbField FieldName="password" Caption="登入密碼" DbType="String" Length="40" /> <DbField FieldName="email" Caption="電子郵件" DbType="String" Length="100" /> <DbField FieldName="note" Caption="備註" DbType="String" Length="200" /> <DbField FieldName="sys_insert_time" DisplayName="寫入時間" DbType="DateTime" /> </Fields> <Indexes> <DbTableIndex Name="pk_{0}" Unique="true" PrimaryKey="true"> <IndexFields> <IndexField FieldName="sys_no" /> </IndexFields> </DbTableIndex> <DbTableIndex Name="rx_{0}" Unique="true"> <IndexFields> <IndexField FieldName="sys_rowid" /> </IndexFields> </DbTableIndex> <DbTableIndex Name="ux_{0}" Unique="true"> <IndexFields> <IndexField FieldName="sys_id" /> </IndexFields> </DbTableIndex> </Indexes> </DbTable> ``` --- ## 7️⃣ 實務價值 1. **快速因應需求變更**:新增欄位或調整型別,只需修改定義檔。 2. **多資料庫佈署彈性**:支援 SQL Server/MySQL/PostgreSQL/Oracle。 3. **一致性與可讀性**:定義檔與資料表結構保持一致,可由框架自動生成對應的物件模型。 4. **長期維護優勢**:降低手動修改風險,符合模組化與低耦合設計。 --- ## ✅ 結語 抽象資料型別讓資料結構設計更具一致性與延展性, DbTable、TableSchemaComparer 與 TableSchemaBuilder 共同構成了 BeeNET 在資料結構層的自動化核心。 透過這樣的架構,ERP 系統能在多資料庫與持續演進的需求下, 仍保持結構一致、部署順暢,並有效降低長期維護成本。 FieldDbType 的設計使開發人員能專注於商業邏輯與流程創新, 而不必被資料庫型別與結構差異所綁架,真正實現高效與穩定並行的開發模式。 --- **📢 歡迎轉載,請註明出處** **📬 歡迎追蹤我的技術筆記與實戰經驗分享** [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)