docs: 更新项目架构与数据模型文档

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scottxjw
2026-08-13 15:01:32 +08:00
parent a3100c73c5
commit 2b031995e1
9 changed files with 678 additions and 885 deletions

View File

@@ -1,16 +1,14 @@
# DbContext 工厂
> 所属模块:[数据库切换支持](./概览.md)
> 所属模块:[数据库支持](./概览.md)
---
## 1. 接口定义
## 1. 本地库工厂
```csharp
// Data/IDbContextFactory.cs
using Gpulse.WCT.DataAnalyzer.Data;
namespace Gpulse.WCT.DataAnalyzer.Data;
// Infrastructure/LocalData/IDbContextFactory.cs
namespace Gpulse.WCT.DataAnalyzer.Core.Infrastructure.LocalData;
public interface IDbContextFactory
{
@@ -18,105 +16,68 @@ public interface IDbContextFactory
}
```
工厂实现读取 `Database:LocalPath`fallback `Database:Path`),支持 SQLite 和 PostgreSQL。
---
## 2. 工厂实现
## 2. 发布库工厂
```csharp
// Data/DbContextFactory.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
// Infrastructure/ReleaseData/IReleaseDbContextFactory.cs
namespace Gpulse.WCT.DataAnalyzer.Core.Infrastructure.ReleaseData;
namespace Gpulse.WCT.DataAnalyzer.Data;
public class DbContextFactory : IDbContextFactory
public interface IReleaseDbContextFactory
{
private readonly IConfiguration _configuration;
public DbContextFactory(IConfiguration configuration)
{
_configuration = configuration;
}
public WctMinerDbContext CreateDbContext()
{
var dbType = _configuration["Database:Type"]?.ToLower() ?? "sqlite";
var optionsBuilder = new DbContextOptionsBuilder<WctMinerDbContext>();
switch (dbType)
{
case "postgresql":
case "postgres":
var pgConnStr = BuildPostgreSqlConnectionString();
optionsBuilder.UseNpgsql(pgConnStr);
break;
case "sqlite":
default:
var dbPath = _configuration["Database:Path"] ?? "./data/database/wctminer.db";
EnsureDirectoryExists(dbPath);
optionsBuilder.UseSqlite($"Data Source={dbPath}");
break;
}
#if DEBUG
optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder.EnableDetailedErrors();
#endif
return new WctMinerDbContext(optionsBuilder.Options);
}
private string BuildPostgreSqlConnectionString()
{
var host = _configuration["Database:Host"] ?? "localhost";
var port = _configuration["Database:Port"] ?? "5432";
var name = _configuration["Database:Name"] ?? "wctminer";
var user = _configuration["Database:User"] ?? "postgres";
var password = _configuration["Database:Password"] ?? "";
return $"Host={host};Port={port};Database={name};Username={user};Password={password}";
}
private static void EnsureDirectoryExists(string dbPath)
{
var directory = Path.GetDirectoryName(dbPath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
ReleaseDbContext CreateDbContext();
}
```
工厂实现读取 `Database:ReleasePath`,支持 SQLite 和 PostgreSQL。PostgreSQL 时使用 `Release*` 前缀配置(`ReleaseHost`, `ReleasePort`, `ReleaseName`, `ReleaseUser`, `ReleasePassword`),未设置时回退到 local 的对应配置。
---
## 3. 依赖注入扩展
## 3. DI 注册
```csharp
// Extensions/ServiceCollectionExtensions.cs
using Microsoft.Extensions.DependencyInjection;
using Gpulse.WCT.DataAnalyzer.Data;
namespace Gpulse.WCT.DataAnalyzer.Extensions;
public static class ServiceCollectionExtensions
// Infrastructure/Extensions/ServiceCollectionExtensions.cs
public static IServiceCollection AddDatabaseServices(
this IServiceCollection services,
IConfiguration configuration)
{
public static IServiceCollection AddDatabaseServices(
this IServiceCollection services,
IConfiguration configuration)
// 本地库
services.AddScoped<IDbContextFactory, DbContextFactory>();
services.AddScoped<WctMinerDbContext>(sp =>
{
// 注册 DbContext 工厂
services.AddScoped<IDbContextFactory, DbContextFactory>();
// 注册 DbContext通过工厂创建
services.AddScoped<WctMinerDbContext>(sp =>
{
var factory = sp.GetRequiredService<IDbContextFactory>();
return factory.CreateDbContext();
});
var factory = sp.GetRequiredService<IDbContextFactory>();
return factory.CreateDbContext();
});
return services;
}
// 发布库(独立)
services.AddScoped<IReleaseDbContextFactory, ReleaseDbContextFactory>();
services.AddScoped<ReleaseDbContext>(sp =>
{
var factory = sp.GetRequiredService<IReleaseDbContextFactory>();
return factory.CreateDbContext();
});
return services;
}
```
## 4. 启动初始化
```csharp
// Program.cs
using var scope = app.Services.CreateScope();
// 初始化本地库
var dbContext = scope.ServiceProvider.GetRequiredService<WctMinerDbContext>();
await dbContext.Database.EnsureCreatedAsync();
// 初始化发布库
var releaseContext = scope.ServiceProvider.GetRequiredService<ReleaseDbContext>();
await releaseContext.Database.EnsureCreatedAsync();
// 本地库种子数据
SeedData.Initialize(dbContext);
```

View File

@@ -1,4 +1,4 @@
# 数据库切换支持
# 数据库切换与双数据库架构
> 所属模块:[架构概览](../概览.md)
@@ -8,38 +8,48 @@
| 文档 | 说明 |
|------|------|
| [DbContext 工厂](./DbContext工厂.md) | 数据库上下文工厂设计 |
| [迁移策略](./迁移策略.md) | 数据库迁移和切换步骤 |
| [DbContext 工厂](./DbContext工厂.md) | 两个数据库上下文工厂设计 |
| [迁移策略](./迁移策略.md) | 数据库迁移步骤 |
---
## 切换策略概览
## 双数据库架构
```
┌─────────────────────────────────────────────────────────────┐
│ appsettings.json │
"Database": { "Type": "sqlite" | "postgresql" }
└─────────────────────────────────────────────────────────────┘
```text
┌─────────────────────────────────────────────────────────────────
appsettings.json
│ Database:LocalPath → local.db
│ Database:ReleasePath → release.db │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ DbContextFactory │
│ 读取配置 → 选择 Provider → 创建 DbContext
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────
DbContextFactory
│ 读取配置 → 选择 Provider → 创建 WctMinerDbContext │
│ ReleaseDbContextFactory │
│ 读取配置 → 选择 Provider → 创建 ReleaseDbContext │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
WctMinerDbContext
统一的 DbModel 配置,适配两种数据库
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────
local.db release.db
──────── ──────────
│ tx_panel charging_parameter │
│ tx_hardware 独立实体,无外键关联 │
│ tx_software │
│ rx_type │
│ test_scenario │
│ qfod_record │
│ ploss_record │
└─────────────────────────────────────────────────────────────────┘
```
---
## 当前状态
| 项目 | 状态 |
|------|------|
| SQLite | ✅ 默认启用 |
| PostgreSQL | ✅ 架构支持,待配置 |
| 切换方式 | 配置文件切换 |
| PostgreSQL | ✅ 架构支持 |
| local.db | ✅ 解析库 |
| release.db | ✅ 发布库 |
| 双库隔离 | ✅ 无外键/导航属性 |

View File

@@ -1,16 +1,17 @@
# 数据库迁移策略
> 所属模块:[数据库切换支持](./概览.md)
> 所属模块:[数据库支持](./概览.md)
---
## 1. 迁移命令
## 1. 本地库迁移
### SQLite
```bash
# 添加迁移
dotnet ef migrations add InitialCreate --output-dir Migrations/SQLite
dotnet ef migrations add InitialCreate --output-dir Migrations/SQLite \
--context WctMinerDbContext --project src/Gpulse.WCT.DataAnalyzer.Core
# 应用迁移
dotnet ef database update
@@ -20,42 +21,43 @@ dotnet ef database update
```bash
# 切换配置后添加迁移
dotnet ef migrations add InitialCreate --output-dir Migrations/PostgreSQL -- --environment PostgreSQL
# 应用迁移
dotnet ef database update -- --environment PostgreSQL
dotnet ef migrations add InitialCreate --output-dir Migrations/PostgreSQL \
--context WctMinerDbContext --project src/Gpulse.WCT.DataAnalyzer.Core \
-- --environment Production
```
---
## 2. 切换步骤
## 2. 发布库迁移
### 从 SQLite 切换到 PostgreSQL
发布库的迁移需要使用 `ReleaseDbContext`
| 步骤 | 操作 | 说明 |
|------|------|------|
| 1 | 修改配置 | `appsettings.json``Database:Type` 改为 `postgresql` |
| 2 | 设置连接 | 配置 `Host`, `Port`, `Name`, `User`, `Password` |
| 3 | 创建数据库 | `CREATE DATABASE wctminer;` |
| 4 | 应用迁移 | `dotnet ef database update` |
| 5 | 数据迁移 | 使用工具迁移 SQLite 数据到 PostgreSQL |
```bash
# 添加迁移
dotnet ef migrations add InitialCreate --output-dir Migrations/Release \
--context ReleaseDbContext --project src/Gpulse.WCT.DataAnalyzer.Core
# 应用迁移
dotnet ef database update --context ReleaseDbContext
```
---
## 3. 配置文件示例
### SQLite (默认)
### SQLite(默认双库)
```json
{
"Database": {
"Type": "sqlite",
"Path": "./data/database/wctminer.db"
"LocalPath": "./data/database/local.db",
"ReleasePath": "./data/database/release.db"
}
}
```
### PostgreSQL
### PostgreSQL(双库独立)
```json
{
@@ -63,9 +65,8 @@ dotnet ef database update -- --environment PostgreSQL
"Type": "postgresql",
"Host": "localhost",
"Port": 5432,
"Name": "wctminer",
"User": "wctminer_user",
"Password": "${DB_PASSWORD}"
"LocalPath": "Server=localhost;Database=wct_local",
"ReleasePath": "Server=db-server;Database=wct_charging_parameters"
}
}
```
@@ -77,5 +78,11 @@ dotnet ef database update -- --environment PostgreSQL
推荐使用 [pgloader](https://github.com/dimitri/pgloader) 迁移 SQLite 到 PostgreSQL
```bash
pgloader ./data/database/wctminer.db postgresql://user:password@localhost:5432/wctminer
```
# 本地库
pgloader ./data/database/local.db postgresql://user:password@localhost:5432/wct_local
# 发布库
pgloader ./data/database/release.db postgresql://user:password@db-server:5432/wct_charging_parameters
```
两个数据库独立迁移,不共享迁移历史。