概念模型 → 逻辑模型完整转换步骤(C#/ 数据库开发通用流程)
概念模型 → 逻辑模型完整转换步骤(C#/数据库开发通用流程)
前置认知
- 概念模型:纯业务ER,只有实体、属性、关系,无数据类型、无主键、无范式、无存储细节,客户/产品能看懂。
- 逻辑模型:规范化程序实体,确定主键、属性、关系约束、消除数据冗余,只关注业务结构,不绑定数据库。
转换核心思路:拆解实体 → 完善属性 → 规范化主键 → 处理实体关系 → 范式去冗余 → 输出标准业务实体(C# Model)
一、完整6步转换流程
步骤1:提取所有业务实体,剔除无关描述
从概念ER图/需求文档里挑出独立业务对象,合并重复名词,删除描述性文字。
示例(林业系统概念模型原始描述)
系统有操作员,记录操作员姓名、登录密码;系统保存文件,每个文件归属文件夹;每次操作生成一条日志,日志记录操作人、操作内容。
提取实体:
- 操作员 Operator
- 文件夹 Folder
- 文件 File
- 操作日志 OperateLog
步骤2:给每个实体梳理全部属性,区分标识属性与普通属性
- 把概念里所有描述整理为实体属性;
- 区分两类属性:
- 标识属性:能唯一区分每条数据(后期做主键)
- 普通属性:业务描述信息
- 统一属性命名(英文驼峰,C#规范)
示例:操作员实体
概念属性:操作员编号、姓名、密码、创建时间
逻辑属性:OperatorId、OperatorName、Password、CreateTime
步骤3:为每个实体定义唯一主键(逻辑主键,无关自增)
概念模型没有主键,逻辑模型必须给每个实体分配唯一标识主键:
- 优先业务主键(身份证、档案编号);
- 无天然唯一业务字段,新增代理主键 Id;
- 主键作用:程序内唯一区分对象,建立关联关系。
示例:
- Operator:主键 OperatorId
- OperateLog:主键 LogId
步骤4:转换实体间关系(一对一/一对多/多对多)
概念只写“谁和谁有关联”,逻辑模型要落地外键、导航关系:
- 一对多(最常见)
一方主键,放到多方作为外键;C#中一方加集合导航属性,多方存外键字段。
例:一个操作员多条日志
- OperateLog 增加外键 OperatorId;
- Operator 增加
List<OperateLog>导航集合。
-
一对一
任意一方存入对方主键作为外键。 -
多对多
概念只写两者关联,逻辑模型必须拆成中间实体,两个外键分别指向双方主键。
例:文件与标签多对多
新增中间实体 FileTag,包含 FileId、TagId 两个外键。
步骤5:应用三大范式,消除数据冗余(逻辑模型核心规范)
这一步是区分“原始概念”和“规范逻辑模型”的关键:
- 第一范式:属性不可再拆分(不能一个字段存多个数据,如地址不分省市区)
- 第二范式:非主键字段完全依赖主键(不能部分依赖)
- 第三范式:非主键字段不依赖其他非主键字段(杜绝传递冗余)
反例(冗余设计,概念模型常见,逻辑层必须优化)
日志实体同时保存 OperatorId、OperatorName
问题:姓名属于操作员信息,存在传递依赖,修改姓名要改全部日志,冗余;
优化:日志只保留 OperatorId,姓名通过关联查询获取。
步骤6:补充业务约束,形成最终逻辑实体
只加业务层面约束(不加数据库存储约束):
- 是否允许为空(业务必填/选填)
- 字段取值范围、枚举(操作类型:新增/删除/修改)
- 唯一约束(用户名不能重复)
不添加:varchar长度、自增、索引、表名等物理信息。
最后输出:纯C#业务实体类(无任何ORM数据库特性标记)
二、完整转换实战案例
原始概念模型(文字版)
实体:操作员、操作日志
关系:一个操作员产生多条操作日志
属性:
操作员:编号、姓名、登录密码
日志:操作编号、操作人姓名、操作内容、操作时间
一步步转换
- 实体:Operator、OperateLog
- 梳理属性,发现冗余:日志存了操作人姓名
- 设置主键:OperatorId、LogId
- 处理一对多关系:日志增加外键 OperatorId,删除冗余 OperatorName
- 三范式校验:无传递依赖,无重复存储
- 补充业务约束:姓名、密码、操作内容不能为空
最终逻辑模型(C#实体,纯业务)
// 逻辑模型:无数据库相关标记
public class Operator
{
// 主键
public long OperatorId { get; set; }
// 业务必填
public string OperatorName { get; set; }
public string Password { get; set; }
public DateTime CreateTime { get; set; }
// 一对多导航属性
public List<OperateLog> OperateLogs { get; set; }
}
public class OperateLog
{
// 主键
public long LogId { get; set; }
// 外键,关联操作员
public long OperatorId { get; set; }
public string Content { get; set; }
public DateTime OperateTime { get; set; }
// 单导航
public Operator Operator { get; set; }
}
三、转换避坑要点
- 不要提前加入数据库细节
逻辑阶段不写长度、自增、表名、索引,这些属于物理模型; - 多对多一定要拆中间表
概念模型可以简化描述,逻辑模型必须拆分为独立实体; - 严格去冗余
概念模型为了好理解会重复存储信息,逻辑模型必须按范式拆分; - 主键统一规划
全部实体统一使用代理Id,便于程序统一管理关联关系; - 约束只区分业务必填,不设计数据库默认值。
四、极简记忆流程
概念(业务名词+关系)
→ 抽取实体属性
→ 设置主键
→ 转换关联、拆分多对多
→ 三范式消除冗余
→ 添加业务约束
= 标准逻辑模型(C#领域实体/Model)

浙公网安备 33010602011771号