BitzOrcas 采用多适配器持久化策略——SqlSugar 为主 ORM,EF Core 作为可选的即插即用适配器,Dapper 用于只读查询场景。三者共享相同的 IUnitOfWork 契约和同一个 CAP Outbox,用于事务性事件发布。
架构
┌──────────────────┐ │ IUnitOfWork │ └────────┬─────────┘ ┌──────────────┼──────────────┐ ▼ ▼ ▼ SqlSugar UoW CapSqlSugar UoW EfCore UoW (仅查询) (CAP Outbox) (CAP Outbox) │ │ │ ▼ ▼ ▼ SqlSugar ORM SqlSugar ORM EF Core ORM + 审计存储 + CAP + 审计 + CAP │ │ │ └──────────────┴──────────────┘ │ ┌──────┴──────┐ │ SQL Server │ └─────────────┘SqlSugar(主 ORM)
BitzOrcas.Infrastructure.SqlSugar 是默认的持久化适配器,提供:
简洁查询 API
SqlSugar 使用流畅查询 API,避免表达式树膨胀:
// 简单查询var notes = await db.Queryable<NoteEntity>() .Where(n => n.TenantId == tenantId) .OrderByDescending(n => n.CreatedAt) .ToListAsync();
// 分页查询var page = await db.Queryable<NoteEntity>() .Where(n => n.TenantId == tenantId) .ToPageListAsync(pageNumber, pageSize, total);全局过滤器(多租户)
SqlSugar 自动应用全局查询过滤器——无需每个查询手动加入:
// 在 DI 中注册一次 — 自动应用于所有查询db.QueryFilter.AddTableFilter<TenantEntityBase>(e => e.TenantId == currentTenantId);db.QueryFilter.AddTableFilter<TenantSoftDeleteEntityBase>(e => e.IsDeleted == false);Schema 初始化
SqlSugar 使用通过 PersistenceModelRegistry 进行的 CodeFirst 自动映射,而非迁移文件:
// 实体通过特性声明元数据[SugarTable("biz_notes")]public class NoteEntity : TenantSoftDeleteEntityBase{ [SugarColumn(Length = 200)] public string Title { get; set; }
[SugarColumn(ColumnDataType = "nvarchar(max)")] public string Content { get; set; }}Schema 通过启动时的 --init-schema 标志初始化——一次完成创建表、索引和种子数据。
审计存储
SqlSugar 提供生产级审计存储后端(SqlSugarAuditLogStore),包含 7 类分片审计表:
SysAuditLog— 一般审计SysActivityLog— 用户活动SysEntityPropertyChangesLog— 属性变更跟踪SysCommunicationLog— API 通信SysExternalRequestLogRecord— 出站 HTTP 调用SysSpecialLog— 特殊事件
CAP Outbox 集成
CapSqlSugarUnitOfWork 桥接 SqlSugar 和 CAP 的 Outbox 模式——领域事件和集成事件在同一数据库事务中原子发布:
// 事件在 Outbox 表中排队,CAP 在提交后发布await unitOfWork.PublishAsync(new NoteCreatedIntegrationEvent(noteId));await unitOfWork.CommitAsync(); // 数据库 + Outbox 原子提交EF Core(可选适配器)
BitzOrcas.Infrastructure.EfCore 提供即插即用替代方案:
- 相同的
IUnitOfWork契约 - 相同的 CAP Outbox 桥接(
DotNetCore.CAP.SqlServer) - 镜像每个 SqlSugar 仓库的 EF Core 等效实现
- 通过配置
Persistence:Provider=EfCore启用
Dapper(只读查询)
BitzOrcas.Infrastructure.Dapper 为需要最大性能的场景提供轻量级只读查询:
// Dapper 用于重读型报表查询const string sql = "SELECT * FROM biz_notes WHERE TenantId = @TenantId";var notes = await connection.QueryAsync<NoteEntity>(sql, new { TenantId = tenantId });实体层次
EntityBase (雪花 Id)├── TenantEntityBase (+ TenantId, 全局过滤器)│ ├── TenantSoftDeleteEntityBase (+ IsDeleted)│ │ └── 所有业务实体 (biz_*)│ └── 身份实体 (sys_*)└── BizEntityBase (业务实体标记)
AuditEntityBase (独立层次,用于分片审计表)├── AuditTenantEntityBase (+ TenantId)└── AuditTenantSoftDeleteEntityBase (+ IsDeleted)配置
{ "ConnectionStrings": { "Default": "Server=localhost;Database=BitzOrcas;User Id=sa;Password=..." }, "Persistence": { "Provider": "SqlSugar" // 或 "EfCore" }, "RabbitMq": { "Host": "localhost", "Port": 5672 }}程序集参考
BitzOrcas.Infrastructure.SqlSugar ├── DependencyInjection.cs → AddBitzOrcasSqlSugarWithCap() ├── SqlSugarUnitOfWork.cs → IUnitOfWork 实现 ├── Cap/ → CapSqlSugarUnitOfWork, Outbox 扩展 ├── Auditing/ → 审计存储 + 实体 + 保留策略 ├── Seeders/ → CsvSeedReader, CsvSeedStepBase ├── Mapping/ → PersistenceModelRegistry, SchemaInitializer └── {Module}/ → 每模块 SqlSugar 仓库
BitzOrcas.Infrastructure.EfCore ├── DependencyInjection.cs → AddBitzOrcasEfCoreWithCap() └── {Module}/ → 每模块 EF Core 仓库
BitzOrcas.Infrastructure.Dapper └── Dapper 查询扩展
BitzOrcas.Infrastructure.Persistence.Models ├── Entities/ → 基础实体层次 ├── Identity/ → Sys* 平台实体 ├── MasterData/ → 主数据实体 └── {Module}/ → 每模块实体