SqlSugar 多库 ConfigId 与按实体选连接
一个进程同时访问业务库、日志库和报表库时,用 ConfigId 注册多套连接,再在仓储层按实体选择连接,业务代码就不必到处传递连接串。
背景与问题
读写分离、审计落独立库、报表走只读副本,这些需求会同时出现。每个服务自己拼连接串,容易连错库、漏关连接,事务和作用域也难以统一。把多套连接收进同一个 ORM 客户端,用稳定的逻辑名区分,连接生命周期才能跟请求走。
做法
启动时注册多份 ConnectionConfig,各自指定 ConfigId。运行时用 GetConnectionScope 按逻辑名取当前作用域里的连接。仓储构造时读取实体上的库标记:操作日志进日志库,业务实体走业务库;报表查询再显式取报表作用域,避免误写只读库。
csharp
services.AddSingleton<ISqlSugarClient>(_ =>
{
return new SqlSugarScope(new List<ConnectionConfig>
{
new()
{
ConfigId = "biz",
ConnectionString = bizCs,
DbType = DbType.SqlServer,
IsAutoCloseConnection = true
},
new()
{
ConfigId = "log",
ConnectionString = logCs,
DbType = DbType.SqlServer,
IsAutoCloseConnection = true
},
new()
{
ConfigId = "report",
ConnectionString = reportCs,
DbType = DbType.SqlServer,
IsAutoCloseConnection = true
},
});
});
csharp
[Tenant("log")]
public class OperationLog { /* ... */ }
string ResolveConfigId(Type entityType)
{
var tenant = entityType.GetCustomAttribute<TenantAttribute>();
return tenant?.configId ?? "biz";
}
var db = client.GetConnectionScope(ResolveConfigId(typeof(TEntity)));
var rows = await db.Queryable<TEntity>().ToListAsync();
标记缺失时回落到业务库,并在启动阶段扫描实体,把未声明目标库的类型打成警告,避免上线后静默写错库。
权衡与陷阱
跨库写操作没有本地事务可以包住两边。需要强一致时把相关表放在同一库;可以接受短暂不一致时,用消息和补偿做最终一致。作用域连接应跟随请求创建和释放。单例服务里不要把某个 ConfigId 的客户端字段缓存下来跨请求复用,否则连接、事务和用户上下文会串到下一次调用。
小结
用 ConfigId 管理多库、用实体特性选择连接,能把「连哪一个库」收拢到基础设施层,让业务服务只处理领域逻辑。