Table of Contents
数据库与数据工具
本页包含会修改数据的命令。执行前先确认目标数据库、停止应用并完成备份。示例命令不会在阅读 Wiki 时自动执行。
1. 支持的数据库
| 数据库 | 推荐场景 | 特点 |
|---|---|---|
| SQLite | 本地开发、测试、演示、单机部署 | 单文件、零外部依赖 |
| MySQL 8.4 | 生产、多实例、集中运维 | 独立服务、连接池、并发能力更强 |
应用启动时会初始化空库结构和基础配置,但不会自动导入学校、考生、考试或报名等演示业务数据。
当前结构版本是 v20。已有数据库版本低于 v20 时,应用会拒绝直接运行并要求先备份和执行明确的升级流程。
2. 数据库目标识别
应用根目录通常是包含 Eis.slnx 或 .env 的目录。
SQLite:
- 默认:
<应用根目录>/data/exam.sqlite SQLITE_PATH相对路径:按应用根目录解析--path:数据库工具命令的显式 SQLite 目标
MySQL:
DATABASE_URL优先;- 否则读取
MYSQL_HOST、MYSQL_PORT、MYSQL_USER、MYSQL_PASSWORD、MYSQL_DATABASE; - 数据库工具确认目标时使用数据库名,不是主机名。
执行任何写操作前,先记录工具输出中的“目标”一行。
3. 建立 MySQL 数据库和账号
示例:
CREATE DATABASE exam_information
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
CREATE USER 'exam_app'@'%'
IDENTIFIED BY 'replace-with-a-strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER
ON exam_information.*
TO 'exam_app'@'%';
应用需要创建和演进表结构,因此账号除了数据读写外还需要 CREATE 和 ALTER。不要授予 MySQL 全局管理员权限。
配置方式见配置参考。
4. 数据库结构
主要关系表包括:
- 组织:
organization、schools、school_classes - 用户:
users、candidate_profiles - 考试:
exams、exam_subjects - 报名:
registrations、registration_subjects - 编排:
test_centers、test_rooms、exam_arrangement_plans、admit_cards、admit_card_subjects - 成绩:
results - 流程:
workflow_definitions、workflow_steps、workflow_instances、workflow_actions - 报名号:
number_rules、number_rule_segments、candidate_account_batches、candidate_account_batch_items - 招生:招生计划、志愿、投档、录取、报到及相关记录
- 公告与审计:
notices、audit_logs - 分表登记:
exam_data_partitions、school_student_partitions - 版本:
schema_metadata
系统还为每场考试和每所学校维护专属物理分表。不要只备份总表或只复制少数业务表。
5. 获取数据库工具
统一发布:
pwsh.exe -NoLogo -NoProfile -NonInteractive -File .\scripts\publish.ps1
工具位于:
artifacts/publish/tools/Eis.Tools.dll
查看帮助:
dotnet .\artifacts\publish\tools\Eis.Tools.dll --help
源码开发时也可以:
dotnet run --project .\src\Eis.Tools\Eis.Tools.csproj -- --help
6. 命令概览
database init 非破坏性建表和基础配置初始化
database reset 重建为空业务库
database seed 导入内置 1200 名考生演示数据
通用参数:
| 参数 | 说明 |
|---|---|
--sqlite |
明确使用 SQLite |
--mysql |
明确使用 MySQL |
--path <文件> |
SQLite 文件路径,只能与 --sqlite 一起使用 |
--confirm-target <目标> |
对破坏性命令确认最终目标 |
--force |
仅 MySQL;允许覆盖无法识别为内置演示数据的业务数据 |
--dry-run |
只预检,不写入 |
--root <目录> |
指定 .env 和相对 SQLite 路径的应用根目录 |
--sqlite 与 --mysql 不能同时使用。database init 不接受 --force。
7. 初始化空库
SQLite
dotnet .\artifacts\publish\tools\Eis.Tools.dll database init `
--sqlite `
--path .\data\exam.sqlite
MySQL
先配置 .env 或进程环境变量,然后:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database init --mysql
init 是非破坏性操作,用于建表和基础配置。它不会导入演示学校、考生或考试。
8. 导入演示数据
演示数据内置于 Eis.Infrastructure.dll,生产服务器不需要 Node.js。
SQLite 安全流程
第一步,只预检:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed `
--sqlite `
--path .\data\demo.sqlite `
--dry-run
第二步,核对工具显示的绝对目标路径。
第三步,明确确认同一目标:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed `
--sqlite `
--path .\data\demo.sqlite `
--confirm-target .\data\demo.sqlite
如果目标文件已存在,工具先复制为:
<数据库文件>.backup-<UTC时间戳>
MySQL 测试库安全流程
第一步:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed --mysql --dry-run
确认输出的数据库名确实是测试库,例如 exam_test。
第二步:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed `
--mysql `
--confirm-target exam_test
如果工具发现无法识别为内置演示数据的业务记录,会拒绝覆盖。只有在已经备份且确认这个测试库可以完全覆盖时才使用:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed `
--mysql `
--confirm-target exam_test `
--force
--force 不会删除数据库本身,但会改写其中的应用数据。不得对生产业务库使用。
9. 演示账号
演示数据中的预置账号密码统一为 12345678:
| 角色 | 账号 |
|---|---|
| 超级管理员 | admin |
| 超级管理员(监督演示) | supervisor |
| 校级管理员 | school_admin |
| 同校校级管理员 | school_admin_2 |
| 班级管理员 | class_admin |
| 同班班级管理员 | class_admin_2 |
| 考生 | 2026-HZ01-F-0001 |
这些账号只存在于演示数据。正常启动空库时不会创建校级、班级或考生样例账号。
10. 测试结束后重建空系统
SQLite
先停止应用:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database reset `
--sqlite `
--path .\data\exam.sqlite `
--confirm-target .\data\exam.sqlite
工具自动备份原 SQLite 文件,然后建立 v20 空业务系统和初始超级管理员。
MySQL
先预检:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database reset --mysql --dry-run
再确认测试数据库名:
dotnet .\artifacts\publish\tools\Eis.Tools.dll database reset `
--mysql `
--confirm-target exam_test
目标包含非演示业务数据时会拒绝。即使使用 --force,也应先完成 MySQL 原生备份。
11. Docker 中维护 SQLite
Compose 默认数据库路径是 /app/data/exam.sqlite,保存在命名卷 exam-information-data。
先停止 Web:
docker compose stop app
再运行工具,目标和确认路径必须完全一致:
docker compose run --rm --entrypoint dotnet app `
/app/tools/Eis.Tools.dll database seed `
--sqlite `
--path /app/data/exam.sqlite `
--confirm-target /app/data/exam.sqlite
完成后启动:
docker compose up --detach app
不要对容器内另一个临时路径执行 seed 后误以为已经修改命名卷数据库。
12. 备份与恢复建议
SQLite
维护前:
- 停止所有使用该文件的 Web 和工具进程。
- 记录数据库绝对路径。
- 复制数据库文件到独立备份目录。
- 保留工具自动生成的时间戳备份。
- 恢复时先停止应用,再用备份文件替换目标。
不要只复制 -wal 或 -shm 文件。应用运行时直接复制数据库可能得到不一致备份,应优先停机。
MySQL
使用组织既有的 MySQL 备份方案,例如逻辑备份、快照或托管服务备份。至少验证:
- 备份包含全部表和结构;
- 恢复到隔离测试库成功;
- 字符集为
utf8mb4; - 应用账号权限仍正确;
- 恢复库结构版本是 v20。
13. 安全保护
数据库工具会:
- 要求破坏性命令明确
--confirm-target; - SQLite 比较最终绝对路径;
- MySQL 比较数据库名;
- 拒绝
mysql、information_schema、performance_schema、sys等系统库; - 校验演示数据和数据库结构版本;
- 默认拒绝覆盖未知 MySQL 业务数据;
- 为已有 SQLite 文件自动建立时间戳备份。
这些保护不能代替人工确认和外部备份。
14. 常见错误
“这是破坏性操作”
缺少 --confirm-target,或确认值和最终目标不一致。重新查看工具输出,不要盲目复制旧命令。
“数据库结构版本低于要求”
当前应用要求 v20。停止上线,保留完整备份,并执行针对旧版本的升级流程;不要用 reset 假装完成生产迁移。
“MySQL 配置不完整”
设置完整 DATABASE_URL,或至少设置 MYSQL_HOST、MYSQL_USER、MYSQL_DATABASE。
“拒绝覆盖非演示业务数据”
目标中存在工具无法确认可覆盖的数据。先核对是否选错库。只有确认是可完全覆盖的测试库并已备份时才考虑 --force。
SQLite 文件没有变化
检查:
--path是否指向预期文件;- 相对路径按哪个
--root解析; - 容器中是否使用
/app/data/exam.sqlite; - Web 是否仍在运行并占用或继续写另一个数据库。