首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >元数据驱动的 ORM 设计报告:从 XML 映射到代码化 Map 体系

元数据驱动的 ORM 设计报告:从 XML 映射到代码化 Map 体系

原创
作者头像
驰骋工作流程
发布于 2026-09-30 08:48:43
发布于 2026-09-30 08:48:43
560
举报

本文基于源码分析梳理一套元数据驱动 ORM 的设计:从早期 XML 映射到代码化 Map 体系,再到主从表、外部数据源与自动建表等扩展机制,并给出与主流 ORM 的对比及适用场景建议。

一、缘起与设计目标

1.1 起始于 2002 年

该平台 ORM 设计起始于 2002 年,起因是探索可复用的企业应用框架技术。当时需要一套能够:

  • 统一描述「数据表 ↔ 实体类」的映射关系;
  • 在多种数据库(SQL Server、Oracle、MySQL 等)上复用同一套业务代码;
  • 支撑快速搭建管理类应用(增删改查、列表查询、主从表编辑)。

EntityDBAccess.cs 文件头注释仍保留着创建时间标记:

1.2 设计目标(与市面 ORM 的差异点)

该平台 ORM 从一开始就不是「纯数据访问层」,而是面向企业低代码应用的元数据框架:

维度

该平台 ORM 目标

典型 ORM(EF Core / Hibernate)目标

核心对象

表 + 字段 + 控件 + 关系

类 + 属性 + 导航属性

元数据载体

Map / Attr / Attrs(代码 + 库表双轨)

特性标注 / Fluent API / 约定

产出物

CRUD + 表单 UI + 查询面板 + 主从/多对多

CRUD + LINQ 查询

运行方式

属性值存于 Row(Hashtable),弱类型读写

强类型属性 + 变更跟踪

这一取向决定了后续 该引擎、该引擎、低代码表单、组织结构等模块均可在同一套元数据上叠加能力,而不必重复定义字段语义。


二、演进历程:XML → Map / Attr / Attrs

2.1 第一阶段:XML 描述映射(约 2002)

早期版本用 XML 文件表达数据表与实体类的完整关系。Map.GenerMap(string xml) 方法至今仍保留这一能力:读取 XML 中的 Base、Attr、SearchAttr、Dtl、Dot2Dot 等节点,动态构建 Map 对象。

XML 方案的优点是映射与代码解耦、便于工具生成;缺点是调试困难、版本管理成本高、缺乏编译期检查。

2.2 第二阶段:Map / Attr / Attrs 类(约 2003)

2003 年,架构改造为以 Map、Attr、Attrs 三个核心类在 C# 代码中描述映射,成为至今沿用的主路径。

类

职责

Map

描述一个实体(En)的完整元数据:物理表名、主键策略、字段集合、从表、多对多、查询条件、关联方法等

Attr

描述单个字段/属性:键名、物理列名、数据类型、字段逻辑类型、UI 控件、可见性、默认值、外键绑定等

Attrs

Attr 的集合,提供 AddTBString、AddTBInt、AddDDLEntities、AddDDLSysEnum 等工厂方法,简化 Map 构建

实体子类通过重写 EnMap 属性返回自己的 Map 定义。以组织结构中的 Emp(用户)为例:

代码化 Map 带来了编译期类型安全(字段常量类如 EmpAttr)、IDE 跳转、与业务逻辑同仓版本管理等优势,XML 路径退居兼容与工具导入用途。


三、核心架构

3.1 类层次与职责

目录结构(引擎内核命名空间):

目录/文件

说明

En/

实体基类、Map/Attr/Attrs、SqlBuilder、QueryObject、EntityDBAccess

DA/

数据库访问、DBAccess、DataType、缓存

Sys/

低代码表单元数据:MapAttr、MapData、MapDtl、SFTable、SFDBSrc

Port/

组织结构实体(Emp、Dept、Station 等),均基于本 ORM 定义

3.2 数据承载:Row 弱类型模型

实体字段值不直接映射为 C# 自动属性,而是存放在 Row(继承 Hashtable) 中,通过 GetValByKey / SetValByKey 读写:

设计意图:

  • 低代码场景下字段可运行时增删,无需重新编译实体类;
  • 主表、从表、流程表单共用同一套读写 API;
  • 业务类仍可封装强类型属性(如 Emp.Name),内部转调 GetValStringByKey。

3.3 持久化流水线

组件

职责

SqlBuilder

根据 Map/Attrs 生成 SELECT/INSERT/UPDATE/DELETE,处理多主键、多数据库方言

SQLCache

缓存实体级 SQL 模板,减少重复拼接

EntityDBAccess

执行 SQL、异常时触发 CheckPhysicsTable 自动建表/扩列

QueryObject

链式构造 WHERE/ORDER BY,供 Entities 批量查询

3.4 主键策略

通过实体基类约定主键字段名:

基类

主键

典型场景

EntityNoName

No(字符串)

部门、用户、角色、流程编号

EntityOID

OID(自增整型)

运行实例、从表明细

EntityMyPK

MyPK(组合字符串)

DeptEmp、DeptEmpStation 等关联表

FieldType 枚举进一步区分字段逻辑角色:普通、主键、外键、枚举、主键+外键、关联文本、虚拟字段等。


四、超越字段映射:BP 扩展能力

原始 ORM 仅解决「数据库列 ↔ 实体属性」映射;该平台 BP 层在此基础上扩展为应用元数据框架。

4.1 字段逻辑类型(FieldType / FieldTypeS)

类型

含义

典型 API

属性字段

普通列,文本框/数值/日期

AddTBString、AddTBInt、AddTBDate

枚举字段

绑定 Sys_Enum 或字符串枚举

AddDDLSysEnum

外键字段

绑定另一 Entities 集合

AddDDLEntities

外部数据源字段

绑定 SFTable(SQL/WS/Handler 等)

UIBindKey → SFTable

关联文本

外键旁的冗余显示列(如 FK_Dept + FK_DeptT)

自动追加 key + "T" 的 Attr

Attr.ToMapAttr 与 MapAttr.HisAttr 构成代码 Map ↔ 库表 MapAttr 双向转换桥梁,使设计态(设计器保存到 Sys_MapAttr)与运行态(GenerMap() 动态生成 Map)保持一致。

4.2 控件类型映射(UIContralType)

Attr 不仅记录 MyDataType(存储类型),还记录 UIContralType(呈现控件):

  • 基础:TB(文本框)、DDL(下拉)、CheckBok、RadioBtn
  • 流程/公文:HandWriting(签名)、FrmImgAth(图片附件)、GovDocFile(正文)、JobSchedule(进度图)
  • 移动端:MapPin、MobilePhoto、Location

低代码表单设计器将控件配置写入 Sys_MapAttr,运行时 MapDtl.GenerMap() 遍历 MapAttrs 调用 map.AddAttr(mapAttr.HisAttr) 合成完整 Map,从而一份元数据同时驱动持久化与 UI 渲染。

4.3 主表—从表映射(EnDtl)

Map.AddDtl 声明主实体下的从表集合:

  • refKey:从表中外键列(如 FK_Node);
  • DtlEditerModel:批量编辑、查询编辑、自定义 URL 等模式;
  • 流程表单明细(MapDtl)、组织结构子面板均基于此机制。

4.4 一对多 / 多对多映射(AttrOfOneVSM)

Map.AttrsOfOneVSM 描述「一」端实体与「多」端实体通过中间表(MM 表)的关联,例如用户维护所属部门:

支持树形部门、平铺面板等多种维护 UI(Dot2DotModel),直接生成部门-人员维护界面,无需手写关联 CRUD。

4.5 外部数据源(SFTable / SFDBSrc)

  • SFTable:定义下拉/列表的外部数据来源(本库 SQL、跨库、WebService、Java 处理器等);
  • SFDBSrc:多数据源连接配置,使 Map 可指定 DBSrc 指向非本地库;
  • 字段通过 UIBindKey 关联 SFTable,实现不建物理外键列也能绑定外部数据的下拉选项。

4.6 自动 DDL(CheckPhysicsTable)

实体在 Insert/Update 失败时可触发 CheckPhysicsTable():按 Map.Attrs 定义自动创建表或扩展列长。这使低代码「先画表单、后建表」成为可能,也是与「迁移脚本驱动」的 ORM 的显著差异。

4.7 查询与权限扩展

Map 还承载:

  • SearchNormals / SearchFKEnums:列表页查询条件;
  • HisRefMethods:实体关联功能(修改密码、部门角色维护等);
  • UAC:插入/删除/更新/查看权限;
  • AddHidden:数据范围过滤(如 SAAS 模式 OrgNo = @WebUser.OrgNo)。

五、生态承载:基于 ORM 构建的产品模块

该平台 ORM 不是孤立的数据层,而是 该引擎 / 该引擎 / 该 BPM 平台 低代码平台 的统一元数据底座。

模块

与 ORM 的关系

该 BPM 平台 / 该引擎

流程模板、节点、表单均用 Entity/Entities 定义;运行期表单数据通过 GEEntity(通用实体)+ 动态 GenerMap() 读写

该引擎

Java 版移植同一套 Map/Attr 语义,保持跨语言元数据一致

低代码

设计器操作 Sys_MapData/Sys_MapAttr;运行时合成 Map;主从表、外键、枚举、外部数据源均落在 Attr 扩展属性上

组织结构

Port_* 五表实体均在 引擎内核命名空间 用 EnMap 声明;DeptEmp、DeptEmpStation 用 EntityMyPK;人员界面用 AttrsOfOneVSM 维护多部门

权限 / 报表 / 接口

统一 GetValByKey 读写;QueryObject 构造列表;ToJsonObject() 输出 API

结论:更换 ORM 意味着重写元数据模型、表单设计器、流程引擎数据层、组织结构集成接口——成本极高,因此该 ORM 是平台级基础设施而非可插拔组件。


六、与市面 ORM 的对比评估

6.1 对比总表

维度

该平台 ORM(引擎内核命名空间)

Entity Framework Core

Hibernate / JPA

Dapper

定位

元数据 + ORM + UI 描述

标准 .NET ORM

Java 标准 ORM

微 ORM / SQL 映射

映射定义

Map/Attr 代码 + Sys_MapAttr 库表

特性 / Fluent API

注解 / XML

手写 SQL

查询方式

QueryObject + SqlBuilder

LINQ

HQL / Criteria / JPQL

原始 SQL

变更跟踪

无(显式 Update)

有

有(Session)

无

UI 元数据

内置(控件、布局、从表)

无

无

无

主从 / 多对多

EnDtl / AttrOfOneVSM 一等公民

导航属性配置

关联映射

自行实现

自动建表

CheckPhysicsTable

Migrations

hbm2ddl

无

多数据库

SqlBuilder 方言分支

提供商插件

方言

取决于 SQL

低代码友好

极高

低

低

低

强类型开发体验

中(Row + 部分封装属性)

高

高

高

学习曲线(纯 CRUD)

中(需理解 Map 体系)

中

中高

低

6.2 该平台 ORM 的优势

  1. 元数据一体:同一 Attr 描述列类型、控件、外键、枚举、默认值,设计器与运行引擎零阻抗。
  2. 企业功能内建:主从表、多对多维护、列表查询、权限位、关联方法,减少重复劳动。
  3. 低代码原生:运行期可 GenerMap(),字段可来自数据库配置,适合用户自定义表单。
  4. 久经生产验证:2002 年至今,与 该引擎 流程场景深度耦合(附件、签名、公文、轨迹等控件类型)。
  5. 多数据库与国产库:EntityDBAccess 内可见 Oracle、MySQL、PostgreSQL、达梦、人大金仓等分支。

6.3 该平台 ORM 的局限

  1. 非标准 ORM:无法直接用于普通 .NET 项目的「引包即用」,与 EF Core 生态(LINQ、迁移、工具链)不兼容。
  2. 弱类型 Row:大型团队纯代码开发时,缺少编译期字段检查,重构依赖全局搜索。
  3. 无现代查询抽象:没有 LINQ / IQueryable,复杂查询依赖 SqlBuilder 字符串,可读性与组合性弱于 EF。
  4. 无变更跟踪:更新需显式调用 Update() 并指定字段,易遗漏或误更新。
  5. XML 遗产:GenerMap(xml) 与代码 EnMap 双路径并存,增加维护心智负担。
  6. 测试与 Mock:Entity 与 DBAccess 静态耦合紧密,单元测试需依赖数据库或大量封装。

6.4 适用场景判断

场景

建议

该 BPM 平台 / 该引擎 / 该引擎 二次开发

必须使用本 ORM,无替代

低代码表单 + 流程 + 组织结构一体部署

最适合

全新 .NET 业务系统、与 BPM 无关

不推荐,应选 EF Core + 独立 DTO

仅需高性能只读查询

可在 Entities 层旁路 DBAccess.RunSQL,但失去元数据收益

与外部 ORM 共存

仅建议边界清晰的数据同步,避免同一表双映射


七、典型开发模式示例

7.1 声明式实体(代码优先)

代码语言:javascript
复制
// 1. 字段常量类
public class XxxAttr { public const string Title = "Title"; }

// 2. 实体类
public class Xxx : EntityNoName
{
    public override Map EnMap
    {
        get
        {
            if (_enMap != null) return _enMap;
            Map map = new Map("My_Xxx", "示例");
            map.AddTBStringPK(XxxAttr.No, null, "编号", true, false, 1, 50, 20);
            map.AddTBString(XxxAttr.Title, null, "标题", true, false, 0, 200, 30);
            map.AddDDLSysEnum("Status", 0, "状态", true, false, "XxxStatus");
            _enMap = map;
            return _enMap;
        }
    }
}

// 3. 集合类
public class Xxxs : EntitiesNoName
{
    public override Entity GetNewEntity => new Xxx();
}

7.2 运行时使用

代码语言:javascript
复制
Xxx en = new Xxx();
en.No = "001";
en.SetValByKey(XxxAttr.Title, "测试");
en.Insert();

Xxxs ens = new Xxxs();
ens.RetrieveByAttr("Status", 1);

Xxx en2 = new Xxx("001");
en2.RetrieveFromDBSources();
string title = en2.GetValStringByKey(XxxAttr.Title);

7.3 低代码动态表单(元数据优先)

  1. 设计器保存字段 → Sys_MapAttr;
  2. MapDtl.GenerMap() / MapData.GenerMap() 合成 Map;
  3. GEDtl / GEEntity 作为通用实体承载数据;
  4. 前端根据 MapAttr JSON 渲染控件。

八、总结

该平台 ORM 是一段从 2002 年 XML 映射演进到 2003 年 Map/Attr/Attrs 代码化元数据、并在二十余年中持续扩展为低代码应用框架底座的技术路线。

它的本质不是「对象—关系映射库」,而是:

用统一的 Map 元数据,同时描述数据库结构、实体行为、UI 控件、主从与多对多关系、外部数据源与查询条件,并驱动 该引擎、该引擎、组织结构与低代码表单的全生命周期。

与 Entity Framework、Hibernate 等市面 ORM 相比,该平台 ORM 在标准性、强类型、现代查询上不占优,但在低代码、流程、表单、组织一体化场景具有不可替代的语义内聚优势。理解这一边界,是正确使用和扩展该 BPM 平台 平台的前提。


原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、缘起与设计目标
    • 1.1 起始于 2002 年
    • 1.2 设计目标(与市面 ORM 的差异点)
  • 二、演进历程:XML → Map / Attr / Attrs
    • 2.1 第一阶段:XML 描述映射(约 2002)
    • 2.2 第二阶段:Map / Attr / Attrs 类(约 2003)
  • 三、核心架构
    • 3.1 类层次与职责
    • 3.2 数据承载:Row 弱类型模型
    • 3.3 持久化流水线
    • 3.4 主键策略
  • 四、超越字段映射:BP 扩展能力
    • 4.1 字段逻辑类型(FieldType / FieldTypeS)
    • 4.2 控件类型映射(UIContralType)
    • 4.3 主表—从表映射(EnDtl)
    • 4.4 一对多 / 多对多映射(AttrOfOneVSM)
    • 4.5 外部数据源(SFTable / SFDBSrc)
    • 4.6 自动 DDL(CheckPhysicsTable)
    • 4.7 查询与权限扩展
  • 五、生态承载:基于 ORM 构建的产品模块
  • 六、与市面 ORM 的对比评估
    • 6.1 对比总表
    • 6.2 该平台 ORM 的优势
    • 6.3 该平台 ORM 的局限
    • 6.4 适用场景判断
  • 七、典型开发模式示例
    • 7.1 声明式实体(代码优先)
    • 7.2 运行时使用
    • 7.3 低代码动态表单(元数据优先)
  • 八、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档