Skip to content
bitzorcas
EN

Reference

持久化构建块

多适配器持久化层 — SqlSugar(主 ORM,简洁查询 API)、可选 EF Core 适配器、Dapper 只读查询,全部统一在 IUnitOfWork 抽象之后。

Last updated

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}/ → 每模块实体