数据访问总览(DbContext / IChameleonDbContext)
DbContext(接口名 IChameleonDbContext,通过 sdk.DbContext 获取,又称"数据库上下文 / 数据库访问 / 数据访问组件")是 Chameleon 平台封装的服务端数据访问接口,提供对业务对象数据的增删改查能力。在 C# 脚本和微服务开发中编写数据库操作代码时,优先使用本组件而非直接操作 ORM。
概述
IChameleonDbContext 是平台层的数据访问抽象,程序集为 Chameleon.Database,命名空间 Chameleon.Database,底层基于 FreeSql ORM(不是 EF Core)。它的核心特征:
- 通过对象编码(
metaObjectCode,如"User.Information")定位数据表,无需强 类型实体类 - 使用
ObjectData(字典结构)作为数据载体,与平台动态模型一致 - 主键固定为
_id(Guid类型),新增时未赋值会自动生成 - 按租户隔离数据库(每租户一个库),无需在 SQL 中手写租户条件
- 自动填充审计字段(
createdby/createdtime/modifiedby/modifiedtime/organization/isdeleted) - 写操作自动产生数据变更审计日志(见数据变更审计)
- 与相邻概念的边界:平台接口的数据操作组件面向可视化编排;
DbContext面向 C# 脚本与微服务中的程序化数据操作。二者操作同一份业务数据。
能力地图
| 能力 | 入口文档 | 典型需求关键词 |
|---|---|---|
| 新增、更新、删除、逻辑删除 | 增删改与逻辑删除 | 保存数据、批量插入、逻辑删除 |
| 按 ID / 按条件查询、分页、排序 | 条件查询与分页 | 查列表、分页查询、查询条数 |
动态过滤条件的构建(DynamicFilter / FilterBuilder) | 过滤条件构建 | where 条件、动态查询条件 |
| 事务(含嵌套事务) | 事务操作 | 原子性、回滚 |
原生 SQL、生成 SQL 文本、获取底层 IFreeSql | SQL 查询与底层实例 | 复杂查询、联表、执行 SQL |
| 数据变更审计日志 | 数据变更审计 | 修改前/修改后的值、审计记录 |
获取方式
在 C# 脚本中使用(推荐)
平台接口的 C# 脚本组件中,通过 ChameleonSDK 参数的 DbContext 属性获取:
public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var db = sdk.DbContext;
var row = await db.GetByIdAsync("LeaveApplication", someId);
return row;
}
在微服务中使用
微服务中通过依赖注入获取接口实例(注册为 Scoped):
public class MyService
{
private readonly IChameleonDbContext _db;
public MyService(IChameleonDbContext db)
{
_db = db;
}
}
全局规约(AI 生成代码必读)
以下约定适用于所有 DbContext 方法,编写任何数据访问代码前必须遵守:
- 优先使用异步版本。每个方法都有
Async后缀的异步版本(如Add/AddAsync),在 C# 脚本与微服务中一律使用异步版本,避免阻塞线程池。 - 面向接口编程。使用
IChameleonDbContext接口上的方法;GetQuerySql/ExecuteDataTable只在实现类ChameleonDbContext上提供,接口上没有,如需使用必须注入具体类。 - 字段名一律小写。
ObjectData的键与查询字段名最终都会转为小写写入 SQL(如createdtime、isdeleted),建议代码中直接使用小写字段编码。 - 对象编码即表名来源。
metaObjectCode中的.会转换为_并整体转小写,如"User.Information"对应表user_information;不要自己拼接表名。 - 查询不会自动过滤已逻辑删除的数据。
isdeleted = true的数据仍会出现在查询结果中,需要排除时必须在过滤条件中显式加FilterBuilder.Eq("isdeleted", false)。 - 不要手动设置审计字段。
createdby/createdtime/modifiedby/modifiedtime/organization/isdeleted由平 台自动填充(已有值则不覆盖)。 - 调用前确保上下文有效。当前请求上下文(
ChameleonContext.Current)中的租户 ID 必须有效,否则抛ArgumentException/InvalidOperationException。
API 方法总览
IChameleonDbContext 完整成员如下(每个方法均有对应的 Async 版本):
public interface IChameleonDbContext
{
// 事务
bool InTransaction { get; } // 是否处于事务中
void Tran(Action func); // 同步事务
TResult Tran<TResult>(Func<TResult> func); // 同步事务(带返回值)
Task TranAsync(Func<Task> func); // 异步事务
Task<TResult> TranAsync<TResult>(Func<Task<TResult>> func); // 异步事务(带返回值)
// 底层实例
IFreeSql GetDatabase(); // 当前租户的 FreeSql 实例
// 新增
int Add(string metaObjectCode, ObjectData objectData); // id 为空自动生成
int BatchAdd(string metaObjectCode, IEnumerable<ObjectData> objectDatas);
// 更新(objectData 必须包含 id)
int Update(string metaObjectCode, ObjectData objectData);
int BatchUpdate(string metaObjectCode, IEnumerable<ObjectData> objectDatas);
// 删除
int Delete(string metaObjectCode, Guid id); // 物理删除
int BatchDelete(string metaObjectCode, Guid[] ids);
int LogicDelete(string metaObjectCode, Guid id); // 逻辑删除(isdeleted = true)
int BatchLogicDelete(string metaObjectCode, Guid[] ids);
// 查询
ObjectData GetById(string metaObjectCode, Guid id, string[] columns = null);
List<ObjectData> GetListByIds(string metaObjectCode, Guid[] ids, string[] columns = null);
List<ObjectData> GetList(string metaObjectCode, DynamicFilter filter, string[] columns = null,
Dictionary<string, int> sort = null, int skip = -1, int limit = -1);
long GetCount(string metaObjectCode, DynamicFilter filter);
bool IsExist(string metaObjectCode, Guid id);
bool IsExist(string metaObjectCode, DynamicFilter filter);
// SQL
List<ObjectData> GetListBySql(string sql, Dictionary<string, object> param = null);
object ExecuteScalar(string sql, Dictionary<string, object> param = null);
}
快速示例
var db = sdk.DbContext;
var entityCode = "LeaveApplication";
// 新增(推荐异步)
await db.AddAsync(entityCode, new ObjectData
{
{ "applicantid", context.UserId },
{ "leavetype", "年假" },
{ "status", "Pending" }
});
// 条件查询(排除已逻辑删除的数据)
var list = await db.GetListAsync(entityCode,
FilterBuilder.And(
FilterBuilder.Eq("status", "Pending"),
FilterBuilder.Eq("isdeleted", false)
),
sort: new Dictionary<string, int> { { "createdtime", -1 } },
skip: 0, limit: 20);
下一步
- 增删改与逻辑删除 -
Add/Update/Delete/LogicDelete的参数与行为 - 条件查询与分页 -
GetList/GetCount/IsExist与分页排序 - 过滤条件构建 -
DynamicFilter模型与FilterBuilder全部操作符 - 事务操作 -
Tran/TranAsync与嵌套事务 - SQL 查询与底层实例 - 原生 SQL、生成 SQL、
GetDatabase() - 数据变更审计 - 写操作的变更日志机制
- 对象触发器 - 想在数据变更后自动执行逻辑时的替代方案