7. 数据库设计
IoT Gateway 使用 Entity Framework Core 作为 ORM 框架,支持多种数据库,如 SQLite、MySQL、PostgreSQL 和 Oracle。数据库设计遵循了关系型数据库的设计原则,具有良好的规范性和可扩展性。


7.1 数据库架构
7.1.1 数据库模型关系图
┌─────────────────────────────────────────────────────────────────┐
│ SystemConfig │
└─────────────────────────────────────────────────────────────────┘
│
└───────────┐
│
┌─────────────────────────────────────────────────────────────────┐
│ Device │
└─────────────────────────────────────────────────────────────────┘
│ 1
│
▼ *
┌─────────────────────────────────────────────────────────────────┐
│ DeviceConfig │
└─────────────────────────────────────────────────────────────────┘
│
▲ *
│ 1
┌─────────────────────────────────────────────────────────────────┐
│ DeviceVariable │
└─────────────────────────────────────────────────────────────────┘
│
▲ *
│ 1
┌─────────────────────────────────────────────────────────────────┐
│ Driver │
└─────────────────────────────────────────────────────────────────┘
│
▲ *
│ 1
┌─────────────────────────────────────────────────────────────────┐
│ RpcLog │
└─────────────────────────────────────────────────────────────────┘
7.2 核心数据模型
7.2.1 SystemConfig(系统配置)
用途:存储系统的全局配置信息
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 配置唯一标识 | 主键,非空 |
| GatewayName | string | 网关名称 | 非空 |
| MqttIp | string | MQTT 服务器 IP | 非空 |
| MqttPort | int | MQTT 服务器端口 | 非空 |
| MqttUName | string | MQTT 用户名 | 非空 |
| MqttUPwd | string | MQTT 密码 | 非空 |
| IoTPlatformType | int | IoT 平台类型 | 非空 |
| CreatedAt | DateTime | 创建时间 | 非空 |
| UpdatedAt | DateTime | 更新时间 | 非空 |
代码实现:
public class SystemConfig : BasePoco
{
[Display(Name = "网关名称")]
public string GatewayName { get; set; }
[Display(Name = "MQTT服务器IP")]
public string MqttIp { get; set; }
[Display(Name = "MQTT服务器端口")]
public int MqttPort { get; set; }
[Display(Name = "MQTT用户名")]
public string MqttUName { get; set; }
[Display(Name = "MQTT密码")]
public string MqttUPwd { get; set; }
[Display(Name = "IoT平台类型")]
public IoTPlatformType IoTPlatformType { get; set; }
}
7.2.2 Device(设备)
用途:存储设备的基本信息
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 设备唯一标识 | 主键,非空 |
| DeviceName | string | 设备名称 | 非空,唯一 |
| DeviceTypeEnum | int | 设备类型 | 非空 |
| DriverId | Guid | 驱动 ID | 外键,非空 |
| AutoStart | bool | 是否自动启动 | 非空,默认 false |
| ParentId | Guid? | 父设备 ID | 外键,可空 |
| CreatedAt | DateTime | 创建时间 | 非空 |
| UpdatedAt | DateTime | 更新时间 | 非空 |
代码实现:
public class Device : BasePoco
{
[Display(Name = "设备名称")]
[Required(ErrorMessage = "设备名称不能为空")]
public string DeviceName { get; set; }
[Display(Name = "设备类型")]
public DeviceTypeEnum DeviceTypeEnum { get; set; }
[Display(Name = "驱动")]
public Guid? DriverId { get; set; }
[Display(Name = "驱动")]
public Driver Driver { get; set; }
[Display(Name = "自动启动")]
public bool AutoStart { get; set; }
[Display(Name = "父设备")]
public Guid? ParentId { get; set; }
[Display(Name = "父设备")]
public Device Parent { get; set; }
[Display(Name = "设备配置")]
public List<DeviceConfig> DeviceConfigs { get; set; }
[Display(Name = "设备变量")]
public List<DeviceVariable> DeviceVariables { get; set; }
}
7.2.3 Driver(驱动)
用途:存储驱动的基本信息
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 驱动唯一标识 | 主键,非空 |
| DriverName | string | 驱动名称 | 非空,唯一 |
| FileName | string | 驱动文件名 | 非空,唯一 |
| AssembleName | string | 驱动程序集名称 | 非空,唯一 |
| CreatedAt | DateTime | 创建时间 | 非空 |
| UpdatedAt | DateTime | 更新时间 | 非空 |
代码实现:
public class Driver : BasePoco
{
[Display(Name = "驱动名称")]
[Required(ErrorMessage = "驱动名称不能为空")]
public string DriverName { get; set; }
[Display(Name = "驱动文件名")]
public string FileName { get; set; }
[Display(Name = "程序集名称")]
public string AssembleName { get; set; }
[Display(Name = "设备")]
public List<Device> Devices { get; set; }
}
7.2.4 DeviceConfig(设备配置)
用途:存储设备的配置信息
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 配置唯一标识 | 主键,非空 |
| DeviceId | Guid | 设备 ID | 外键,非空 |
| DeviceConfigName | string | 配置名称 | 非空 |
| Value | string | 配置值 | 非空 |
| DataSide | int | 数据方向 | 非空 |
| Description | string | 描述 | 可空 |
| EnumInfo | string | 枚举信息 | 可空 |
| CreatedAt | DateTime | 创建时间 | 非空 |
| UpdatedAt | DateTime | 更新时间 | 非空 |
代码实现:
public class DeviceConfig : BasePoco
{
[Display(Name = "设备")]
public Guid? DeviceId { get; set; }
[Display(Name = "设备")]
public Device Device { get; set; }
[Display(Name = "配置名称")]
public string DeviceConfigName { get; set; }
[Display(Name = "配置值")]
public string Value { get; set; }
[Display(Name = "数据方向")]
public DataSide DataSide { get; set; }
[Display(Name = "描述")]
public string Description { get; set; }
[Display(Name = "枚举信息")]
public string EnumInfo { get; set; }
}
7.2.5 DeviceVariable(设备变量)
用途:存储设备变量的信息
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 变量唯一标识 | 主键,非空 |
| DeviceId | Guid | 设备 ID | 外键,非空 |
| Name | string | 变量名称 | 非空 |
| DeviceAddress | string | 设备地址 | 非空 |
| DataType | string | 数据类型 | 非空 |
| Method | string | 采集方法 | 非空 |
| Expressions | string | 表达式 | 可空 |
| CreatedAt | DateTime | 创建时间 | 非空 |
| UpdatedAt | DateTime | 更新时间 | 非空 |
代码实现:
public class DeviceVariable : BasePoco, IVariable
{
[Display(Name = "设备")]
public Guid? DeviceId { get; set; }
[Display(Name = "设备")]
public Device Device { get; set; }
[Display(Name = "变量名称")]
[Required(ErrorMessage = "变量名称不能为空")]
public string Name { get; set; }
[Display(Name = "设备地址")]
[Required(ErrorMessage = "设备地址不能为空")]
public string DeviceAddress { get; set; }
[Display(Name = "数据类型")]
[Required(ErrorMessage = "数据类型不能为空")]
public string DataType { get; set; }
[Display(Name = "采集方法")]
[Required(ErrorMessage = "采集方法不能为空")]
public string Method { get; set; }
[Display(Name = "表达式")]
public string Expressions { get; set; }
}
7.2.6 RpcLog(RPC 日志)
用途:存储 RPC 命令的执行日志
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 日志唯一标识 | 主键,非空 |
| DeviceId | Guid | 设备 ID | 外键,非空 |
| Method | string | 方法名称 | 非空 |
| Params | string | 参数 | 可空 |
| IsSuccess | bool | 是否成功 | 非空,默认 false |
| Description | string | 描述 | 可空 |
| StartTime | DateTime | 开始时间 | 非空 |
| EndTime | DateTime | 结束时间 | 可空 |
| RpcSide | int | RPC 方向 | 非空 |
| CreatedAt | DateTime | 创建时间 | 非空 |
代码实现:
public class RpcLog : BasePoco
{
[Display(Name = "设备")]
public Guid? DeviceId { get; set; }
[Display(Name = "设备")]
public Device Device { get; set; }
[Display(Name = "方法")]
public string Method { get; set; }
[Display(Name = "参数")]
public string Params { get; set; }
[Display(Name = "是否成功")]
public bool IsSuccess { get; set; }
[Display(Name = "描述")]
public string Description { get; set; }
[Display(Name = "开始时间")]
public DateTime StartTime { get; set; }
[Display(Name = "结束时间")]
public DateTime? EndTime { get; set; }
[Display(Name = "RPC方向")]
public RpcSide RpcSide { get; set; }
}
7.2.7 FrameworkUser(框架用户)
用途:存储系统用户信息
| 字段名 | 数据类型 | 描述 | 约束 |
|---|---|---|---|
| ID | Guid | 用户唯一标识 | 主键,非空 |
| ITCode | string | 用户账号 | 非空,唯一 |
| Password | string | 密码 | 非空 |
| Name | string | 用户名称 | 非空 |
| string | 邮箱 | 可空 | |
| PhoneNumber | string | 电话号码 | 可空 |
| IsValid | bool | 是否有效 | 非空,默认 true |
| CreatedAt | DateTime | 创建时间 | 非空 |
| UpdatedAt | DateTime | 更新时间 | 非空 |
代码实现:
public class FrameworkUser : BasePoco
{
[Display(Name = "用户账号")]
[Required(ErrorMessage = "用户账号不能为空")]
public string ITCode { get; set; }
[Display(Name = "密码")]
[Required(ErrorMessage = "密码不能为空")]
public string Password { get; set; }
[Display(Name = "用户名称")]
[Required(ErrorMessage = "用户名称不能为空")]
public string Name { get; set; }
[Display(Name = "邮箱")]
public string Email { get; set; }
[Display(Name = "电话号码")]
public string PhoneNumber { get; set; }
[Display(Name = "是否有效")]
public bool IsValid { get; set; }
}
7.3 数据上下文
7.3.1 DataContext 设计
DataContext 是 Entity Framework Core 的核心组件,负责数据库连接和数据操作。
代码实现:
public class DataContext : WTMContext
{
public DataContext(string cs, DBTypeEnum dbtype) : base(cs, dbtype)
{
}
public DataContext(string cs, DBTypeEnum dbtype, Action<DbContextOptionsBuilder> options) : base(cs, dbtype, options)
{
}
public DbSet<Device> Devices { get; set; }
public DbSet<Driver> Drivers { get; set; }
public DbSet<DeviceConfig> DeviceConfigs { get; set; }
public DbSet<DeviceVariable> DeviceVariables { get; set; }
public DbSet<SystemConfig> SystemConfigs { get; set; }
public DbSet<RpcLog> RpcLogs { get; set; }
public DbSet<FrameworkUser> FrameworkUsers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// 模型配置
// ...
}
}
7.3.2 数据库连接配置
数据库连接配置存储在 appsettings.json 文件中:
{
"Connections": [
{
"Name": "Default",
"DBType": "sqlite",
"Value": "Data Source=iotgateway.db"
}
]
}
7.4 数据库迁移
7.4.1 迁移文件
数据库迁移文件位于 IoTGateway.DataAccess/Migrations 目录下,包含了数据库结构的变更历史。
迁移文件示例:
public partial class ini : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Drivers",
columns: table => new
{
ID = table.Column<Guid>(type: "TEXT", nullable: false),
DriverName = table.Column<string>(type: "TEXT", nullable: true),
FileName = table.Column<string>(type: "TEXT", nullable: true),
AssembleName = table.Column<string>(type: "TEXT", nullable: true),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Drivers", x => x.ID);
});
// 其他表的创建语句
// ...
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// 表删除语句
// ...
}
}
7.4.2 迁移命令
使用以下命令进行数据库迁移:
# 添加迁移
cd IoTGateway.DataAccess
dotnet ef migrations add <MigrationName> --startup-project ../IoTGateway
# 更新数据库
dotnet ef database update --startup-project ../IoTGateway
# 删除迁移
dotnet ef migrations remove --startup-project ../IoTGateway
7.5 数据库优化
7.5.1 索引设计
为经常查询的字段添加索引,提高查询性能:
| 表名 | 字段名 | 索引类型 | 描述 |
|---|---|---|---|
| Device | DeviceName | 唯一索引 | 设备名称唯一,用于快速查询 |
| Device | DriverId | 普通索引 | 用于关联查询驱动下的设备 |
| DeviceVariable | DeviceId | 普通索引 | 用于关联查询设备下的变量 |
| RpcLog | DeviceId | 普通索引 | 用于关联查询设备的 RPC 日志 |
| RpcLog | StartTime | 普通索引 | 用于按时间范围查询 RPC 日志 |
7.5.2 查询优化
-
使用延迟加载,减少不必要的数据加载
-
使用预加载(Include),减少 N+1 查询问题
-
使用分页查询,减少数据传输量
-
避免在循环中执行数据库操作
7.5.3 事务管理
-
关键操作使用事务,确保数据一致性
-
合理设置事务隔离级别
-
避免长事务,减少锁竞争
7.6 数据库备份与恢复
7.6.1 备份策略
-
定期自动备份
-
手动备份选项
-
备份文件压缩和加密
-
备份文件异地存储
7.6.2 恢复策略
-
支持从备份文件恢复
-
恢复前的数据验证
-
恢复后的完整性检查
7.7 数据库安全
7.7.1 访问控制
-
使用最小权限原则配置数据库用户
-
限制数据库访问 IP
-
定期更换数据库密码
7.7.2 数据加密
-
敏感数据加密存储
-
数据库连接字符串加密
-
传输过程加密(SSL/TLS)
7.7.3 审计日志
-
记录数据库操作日志
-
监控异常访问
-
定期审计数据库访问
7.8 多数据库支持
7.8.1 数据库适配
IoT Gateway 支持多种数据库,通过 Entity Framework Core 实现数据库适配:
-
SQLite:轻量级数据库,适合开发和小型应用
-
MySQL:开源关系型数据库,适合中大型应用
-
PostgreSQL:功能强大的开源关系型数据库,支持高级特性
-
Oracle:企业级关系型数据库,适合大型应用
7.8.2 数据库切换
切换数据库只需修改 appsettings.json 中的数据库连接配置:
// SQLite
{
"Connections": [
{
"Name": "Default",
"DBType": "sqlite",
"Value": "Data Source=iotgateway.db"
}
]
}
// MySQL
{
"Connections": [
{
"Name": "Default",
"DBType": "mysql",
"Value": "Server=localhost;Database=iotgateway;User=root;Password=123456;"
}
]
}
// PostgreSQL
{
"Connections": [
{
"Name": "Default",
"DBType": "pgsql",
"Value": "Host=localhost;Database=iotgateway;Username=postgres;Password=123456;"
}
]
}
7.9 数据库监控
7.9.1 性能监控
-
监控数据库连接数
-
监控查询响应时间
-
监控数据库资源使用情况
7.9.2 健康检查
-
定期检查数据库连接状态
-
检查数据库完整性
-
检查数据库索引状态
7.9.3 告警机制
-
数据库连接失败告警
-
慢查询告警
-
数据库空间不足告警
7.10 最佳实践
7.10.1 设计原则
-
遵循第三范式
-
合理设计主键和外键
-
适当冗余,提高查询性能
-
考虑数据增长趋势
7.10.2 开发规范
-
使用统一的命名规范
-
添加必要的注释
-
编写单元测试
-
定期进行代码审查
7.10.3 部署建议
-
生产环境使用独立的数据库服务器
-
配置合理的数据库参数
-
定期进行数据库优化
-
建立完善的备份和恢复机制
文档版本 :1.0 更新日期 :2025-11-29 编写人员:辉为科技