156 lines
5.8 KiB
Markdown
156 lines
5.8 KiB
Markdown
|
|
# TransactionRecordRepository 重构总结
|
|||
|
|
|
|||
|
|
## 重构目标
|
|||
|
|
|
|||
|
|
简化账单仓储,移除内存聚合逻辑,将聚合逻辑移到Service层,提高代码可测试性和可维护性。
|
|||
|
|
|
|||
|
|
## 主要变更
|
|||
|
|
|
|||
|
|
### 1. 创建新的仓储层 (TransactionRecordRepository.cs)
|
|||
|
|
|
|||
|
|
**简化后的接口方法:**
|
|||
|
|
- `QueryAsync` - 统一的查询方法,支持多种筛选条件和分页
|
|||
|
|
- `CountAsync` - 统一的计数方法
|
|||
|
|
- `GetDistinctClassifyAsync` - 获取所有分类
|
|||
|
|
- `GetByEmailIdAsync` - 按邮件ID查询
|
|||
|
|
- `GetUnclassifiedAsync` - 获取未分类账单
|
|||
|
|
- `GetClassifiedByKeywordsAsync` - 关键词查询已分类账单
|
|||
|
|
- `GetUnconfirmedRecordsAsync` - 获取待确认账单
|
|||
|
|
- `BatchUpdateByReasonAsync` - 批量更新分类
|
|||
|
|
- `UpdateCategoryNameAsync` - 更新分类名称
|
|||
|
|
- `ConfirmAllUnconfirmedAsync` - 确认待确认分类
|
|||
|
|
- `ExistsByEmailMessageIdAsync` - 检查邮件是否存在
|
|||
|
|
- `ExistsByImportNoAsync` - 检查导入编号是否存在
|
|||
|
|
|
|||
|
|
**移除的方法(移到Service层):**
|
|||
|
|
- `GetDailyStatisticsAsync` - 日统计
|
|||
|
|
- `GetDailyStatisticsByRangeAsync` - 范围日统计
|
|||
|
|
- `GetMonthlyStatisticsAsync` - 月度统计
|
|||
|
|
- `GetCategoryStatisticsAsync` - 分类统计
|
|||
|
|
- `GetTrendStatisticsAsync` - 趋势统计
|
|||
|
|
- `GetReasonGroupsAsync` - 按摘要分组统计
|
|||
|
|
- `GetClassifiedByKeywordsWithScoreAsync` - 关键词匹配(带分数)
|
|||
|
|
- `GetFilteredTrendStatisticsAsync` - 过滤趋势统计
|
|||
|
|
- `GetAmountGroupByClassifyAsync` - 按分类分组统计
|
|||
|
|
|
|||
|
|
### 2. 创建统计服务层 (TransactionStatisticsService.cs)
|
|||
|
|
|
|||
|
|
新增 `ITransactionStatisticsService` 接口和实现,负责所有聚合统计逻辑:
|
|||
|
|
|
|||
|
|
**主要方法:**
|
|||
|
|
- `GetDailyStatisticsAsync` - 日统计(内存聚合)
|
|||
|
|
- `GetDailyStatisticsByRangeAsync` - 范围日统计(内存聚合)
|
|||
|
|
- `GetMonthlyStatisticsAsync` - 月度统计(内存聚合)
|
|||
|
|
- `GetCategoryStatisticsAsync` - 分类统计(内存聚合)
|
|||
|
|
- `GetTrendStatisticsAsync` - 趋势统计(内存聚合)
|
|||
|
|
- `GetReasonGroupsAsync` - 按摘要分组统计(内存聚合,解决N+1问题)
|
|||
|
|
- `GetClassifiedByKeywordsWithScoreAsync` - 关键词匹配(内存计算相关度)
|
|||
|
|
- `GetFilteredTrendStatisticsAsync` - 过滤趋势统计(内存聚合)
|
|||
|
|
- `GetAmountGroupByClassifyAsync` - 按分类分组统计(内存聚合)
|
|||
|
|
|
|||
|
|
### 3. 创建DTO文件 (TransactionStatisticsDto.cs)
|
|||
|
|
|
|||
|
|
将统计相关的DTO类从Repository移到独立文件:
|
|||
|
|
- `ReasonGroupDto` - 按摘要分组统计DTO
|
|||
|
|
- `MonthlyStatistics` - 月度统计数据
|
|||
|
|
- `CategoryStatistics` - 分类统计数据
|
|||
|
|
- `TrendStatistics` - 趋势统计数据
|
|||
|
|
|
|||
|
|
### 4. 更新Controller (TransactionRecordController.cs)
|
|||
|
|
|
|||
|
|
- 注入 `ITransactionStatisticsService`
|
|||
|
|
- 将所有统计方法的调用从 `transactionRepository` 改为 `transactionStatisticsService`
|
|||
|
|
- 将 `GetPagedListAsync` 改为 `QueryAsync`
|
|||
|
|
- 将 `GetTotalCountAsync` 改为 `CountAsync`
|
|||
|
|
- 将 `GetByDateRangeAsync` 改为 `QueryAsync`
|
|||
|
|
- 将 `GetUnclassifiedCountAsync` 改为 `CountAsync`
|
|||
|
|
|
|||
|
|
### 5. 更新Service层
|
|||
|
|
|
|||
|
|
**SmartHandleService:**
|
|||
|
|
- 注入 `ITransactionStatisticsService`
|
|||
|
|
- 将 `GetClassifiedByKeywordsWithScoreAsync` 调用改为使用统计服务
|
|||
|
|
|
|||
|
|
**BudgetService:**
|
|||
|
|
- 注入 `ITransactionStatisticsService`
|
|||
|
|
- 将 `GetCategoryStatisticsAsync` 调用改为使用统计服务
|
|||
|
|
|
|||
|
|
**BudgetStatsService:**
|
|||
|
|
- 注入 `ITransactionStatisticsService`
|
|||
|
|
- 将所有 `GetFilteredTrendStatisticsAsync` 调用改为使用统计服务
|
|||
|
|
|
|||
|
|
**BudgetSavingsService:**
|
|||
|
|
- 注入 `ITransactionStatisticsService`
|
|||
|
|
- 将所有 `GetAmountGroupByClassifyAsync` 调用改为使用统计服务
|
|||
|
|
|
|||
|
|
### 6. 更新测试文件
|
|||
|
|
|
|||
|
|
**BudgetStatsTest.cs:**
|
|||
|
|
- 添加 `ITransactionStatisticsService` Mock
|
|||
|
|
- 更新构造函数参数
|
|||
|
|
- 将所有 `GetFilteredTrendStatisticsAsync` Mock调用改为使用统计服务
|
|||
|
|
|
|||
|
|
**BudgetSavingsTest.cs:**
|
|||
|
|
- 添加 `ITransactionStatisticsService` Mock
|
|||
|
|
- 更新构造函数参数
|
|||
|
|
- 将所有 `GetAmountGroupByClassifyAsync` Mock调用改为使用统计服务
|
|||
|
|
|
|||
|
|
## 重构优势
|
|||
|
|
|
|||
|
|
### 1. 职责分离
|
|||
|
|
- **Repository层**:只负责数据查询,返回原始数据
|
|||
|
|
- **Service层**:负责业务逻辑和数据聚合
|
|||
|
|
|
|||
|
|
### 2. 可测试性提升
|
|||
|
|
- Repository层的方法更简单,易于Mock
|
|||
|
|
- Service层可以独立测试聚合逻辑
|
|||
|
|
- 测试时可以精确控制聚合行为
|
|||
|
|
|
|||
|
|
### 3. 性能优化
|
|||
|
|
- 解决了 `GetReasonGroupsAsync` 中的N+1查询问题
|
|||
|
|
- 将内存聚合逻辑集中管理,便于后续优化
|
|||
|
|
- 减少了数据库聚合操作,避免大数据量时的性能问题
|
|||
|
|
|
|||
|
|
### 4. 代码可维护性
|
|||
|
|
- 统一的查询接口 `QueryAsync` 和 `CountAsync`
|
|||
|
|
- 减少了代码重复
|
|||
|
|
- 更清晰的职责划分
|
|||
|
|
|
|||
|
|
### 5. 扩展性
|
|||
|
|
- 新增统计功能只需在Service层添加
|
|||
|
|
- Repository层保持稳定,不受业务逻辑变化影响
|
|||
|
|
|
|||
|
|
## 测试结果
|
|||
|
|
|
|||
|
|
所有测试通过:
|
|||
|
|
- BudgetStatsTest: 7个测试全部通过
|
|||
|
|
- BudgetSavingsTest: 7个测试全部通过
|
|||
|
|
- 总计: 14个测试全部通过
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
### 1. 性能考虑
|
|||
|
|
- 当前使用内存聚合,适合中小数据量
|
|||
|
|
- 如果数据量很大,可以考虑在Service层使用分页查询+增量聚合
|
|||
|
|
- 对于需要实时聚合的场景,可以考虑缓存
|
|||
|
|
|
|||
|
|
### 2. 警告处理
|
|||
|
|
编译时有3个未使用参数的警告:
|
|||
|
|
- `TransactionStatisticsService` 的 `textSegmentService` 参数未使用
|
|||
|
|
- `BudgetStatsService` 的 `transactionRecordRepository` 参数未使用
|
|||
|
|
- `BudgetSavingsService` 的 `transactionsRepository` 参数未使用
|
|||
|
|
|
|||
|
|
这些参数暂时保留,可能在未来使用,可以通过添加 `_ = parameter;` 来消除警告。
|
|||
|
|
|
|||
|
|
### 3. 向后兼容
|
|||
|
|
- Controller的API接口保持不变
|
|||
|
|
- 前端无需修改
|
|||
|
|
- 数据库结构无变化
|
|||
|
|
|
|||
|
|
## 后续优化建议
|
|||
|
|
|
|||
|
|
1. **添加缓存**:对于频繁查询的统计数据,可以添加缓存机制
|
|||
|
|
2. **分页聚合**:对于大数据量的聚合,可以实现分页聚合策略
|
|||
|
|
3. **异步优化**:某些聚合操作可以并行执行以提高性能
|
|||
|
|
4. **监控指标**:添加聚合查询的性能监控
|
|||
|
|
5. **单元测试**:为 `TransactionStatisticsService` 添加专门的单元测试
|