178 lines
5.9 KiB
Markdown
178 lines
5.9 KiB
Markdown
# 低代码平台数据源抽象架构说明
|
||
|
||
## 概述
|
||
|
||
低代码平台已重构为基于数据源提供者(Provider)模式的可扩展架构,支持多数据源、配置驱动的代码生成。
|
||
|
||
## 核心架构
|
||
|
||
### 1. 抽象层 (Abstractions)
|
||
|
||
#### IDataSourceProvider
|
||
数据源提供者接口,定义了所有数据源必须实现的功能:
|
||
- `Config`: 数据源配置信息
|
||
- `GetTables()`: 获取数据库表信息
|
||
- `GetDbContext()`: 获取数据库上下文
|
||
|
||
#### DataSourceConfig
|
||
数据源配置模型,包含:
|
||
- **DatabaseKey**: 数据库标识(如:Admin, MiaoYuChat, LiveForum)
|
||
- **路径模板**: 支持占位符的路径配置
|
||
- `{RootPath}`: 项目根路径
|
||
- `{AppPath}`: 应用路径
|
||
- `{Namespace}`: 实体命名空间
|
||
- `{EntityName}`: 实体名称
|
||
- `{EntityNamePlural}`: 实体名称复数形式
|
||
- `{TableName}`: 表名
|
||
- **TemplatePath**: 代码生成模板目录
|
||
- **NamingStrategy**: 实体命名策略(保持原名/驼峰转换)
|
||
|
||
#### EntityNamingStrategy
|
||
命名策略枚举:
|
||
- `KeepOriginal`: 保持数据库表名原样
|
||
- `ToPascalCase`: 转换为驼峰命名(去除下划线前缀)
|
||
|
||
### 2. 核心工具 (Core)
|
||
|
||
#### DataSourceManager
|
||
数据源管理器,负责:
|
||
- 自动收集所有注册的 `IDataSourceProvider`
|
||
- 根据DatabaseKey获取对应的Provider
|
||
- 聚合所有数据源的表信息
|
||
|
||
#### PathResolver
|
||
路径解析器,负责:
|
||
- 解析路径模板中的占位符
|
||
- 应用命名策略转换
|
||
- 生成最终的文件路径
|
||
|
||
#### DataSourceExtensions
|
||
扩展方法集,提供:
|
||
- `ExtractDatabaseKey()`: 从Schema中提取数据库标识
|
||
- `CleanSchema()`: 清理Schema中的数据库标识
|
||
|
||
### 3. 数据源实现 (Providers)
|
||
|
||
#### AdminDataSourceProvider
|
||
后台管理系统数据源:
|
||
- DatabaseKey: `Admin`
|
||
- NamingStrategy: `ToPascalCase`(驼峰转换)
|
||
- 模板路径: `/wwwroot/code_generation/template/`
|
||
- 实体目录: 按复数形式分类(如 `Entities\\Apps\\Users`)
|
||
|
||
#### MiaoYuChatDataSourceProvider
|
||
喵语AI聊天数据源:
|
||
- DatabaseKey: `MiaoYuChat`
|
||
- NamingStrategy: `KeepOriginal`(保持原名)
|
||
- 模板路径: `/wwwroot/code_generation/templatev4/`
|
||
- 实体目录: 扁平结构(如 `Entities\\Apps`)
|
||
|
||
## 新增数据源步骤
|
||
|
||
### 1. 创建Provider实现
|
||
|
||
在 `Providers` 目录下创建新的Provider类:
|
||
|
||
```csharp
|
||
public class NewDataSourceProvider : IDataSourceProvider, IScopedDependency
|
||
{
|
||
private readonly IRepository<YourEntity> _repository;
|
||
|
||
public NewDataSourceProvider(IRepository<YourEntity> repository)
|
||
{
|
||
_repository = repository;
|
||
}
|
||
|
||
public DataSourceConfig Config => new DataSourceConfig
|
||
{
|
||
DatabaseKey = DataSourceConstants.YourDatabase,
|
||
DisplayName = "数据库显示名称",
|
||
EntityNamespace = typeof(YourRepositoryStartup).Namespace!,
|
||
ModelPathTemplate = "{RootPath}\\{Namespace}\\Entities\\YourPath",
|
||
ServicePathTemplate = "{AppPath}\\ApplicationServices\\YourPath",
|
||
ControllerPathTemplate = "{AppPath}\\Controllers\\YourPath",
|
||
ClientIndexPathTemplate = "{RootPath}\\admin-client\\src\\views\\YourPath",
|
||
ClientInfoPathTemplate = "{RootPath}\\admin-client\\src\\views\\YourPath",
|
||
ClientServicePathTemplate = "{RootPath}\\admin-client\\src\\services\\YourPath",
|
||
TemplatePath = "/wwwroot/code_generation/template/",
|
||
NamingStrategy = EntityNamingStrategy.ToPascalCase,
|
||
Order = 3
|
||
};
|
||
|
||
public List<DbTableInfo> GetTables()
|
||
{
|
||
var tables = _repository.UnitOfWork.FreeSqlOrm.DbFirst.GetTablesByDatabase();
|
||
// 标记数据源来源
|
||
tables.ForEach(t => t.Schema = t.Schema + "." + Config.DatabaseKey);
|
||
return tables;
|
||
}
|
||
|
||
public DbContext GetDbContext() => _repository.GetContext()!;
|
||
}
|
||
```
|
||
|
||
### 2. 添加常量定义
|
||
|
||
在 `DataSourceConstants` 中添加新的数据库标识:
|
||
|
||
```csharp
|
||
public const string YourDatabase = "YourDatabase";
|
||
```
|
||
|
||
### 3. 自动注册
|
||
|
||
由于Provider类实现了 `IScopedDependency`,依赖注入系统会自动注册。
|
||
`DataSourceManager` 会在构造函数中自动收集所有Provider实例。
|
||
|
||
### 4. 验证
|
||
|
||
启动项目后:
|
||
1. 表同步功能会自动识别新数据源
|
||
2. 代码生成会根据新配置生成相应代码
|
||
3. 无需修改任何业务逻辑代码
|
||
|
||
## 关键服务说明
|
||
|
||
### DatabaseTableService
|
||
- `GetAllTableInfos()`: 获取所有数据源的表信息(通过DataSourceManager聚合)
|
||
|
||
### CodeGenerationService
|
||
- `FillPathByLowCodeTable()`: 根据数据源配置填充路径
|
||
- `GenModelAsync()`: 根据数据源模板生成Model代码
|
||
- `GenServiceAsync()`: 生成Service代码
|
||
- `GenControllerAsync()`: 生成Controller代码
|
||
- `GenIndexAsync()`: 生成前端Index页面
|
||
- `GenInfoAsync()`: 生成前端Info页面
|
||
- `GenServiceJsAsync()`: 生成前端Service代码
|
||
|
||
### LowCodeTableService
|
||
- `SynchronizationAsync()`: 同步所有数据源的表到低代码系统
|
||
- 自动识别数据源
|
||
- 应用相应的命名策略
|
||
- 保存数据库标识和Schema信息
|
||
|
||
## 优势
|
||
|
||
1. **开放封闭原则**: 新增数据源无需修改现有代码,只需添加Provider
|
||
2. **配置驱动**: 所有路径和行为都通过配置控制
|
||
3. **类型安全**: 使用强类型配置,编译时验证
|
||
4. **可维护性**: 每个数据源的逻辑独立,互不影响
|
||
5. **可测试性**: Provider可独立测试,易于Mock
|
||
|
||
## 注意事项
|
||
|
||
1. Provider必须实现 `IScopedDependency` 才能被自动注册
|
||
2. `GetTables()` 中需要标记Schema以区分数据源:`t.Schema += "." + DatabaseKey`
|
||
3. 路径模板中的占位符大小写敏感
|
||
4. Order属性控制数据源的显示顺序,数字越小越靠前
|
||
5. NamingStrategy影响实体类的命名,需根据数据库命名规范选择
|
||
|
||
## 扩展性考虑
|
||
|
||
当前架构支持以下扩展:
|
||
- 新的命名策略(需扩展EntityNamingStrategy枚举)
|
||
- 自定义路径占位符(需扩展PathResolver)
|
||
- 不同的模板引擎(需修改代码生成服务)
|
||
- 多租户数据源(需在Provider中实现动态配置)
|
||
|