跳到主要内容

数据访问总览(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 文本、获取底层 IFreeSqlSQL 查询与底层实例复杂查询、联表、执行 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 方法,编写任何数据访问代码前必须遵守:

  1. 优先使用异步版本。每个方法都有 Async 后缀的异步版本(如 Add / AddAsync),在 C# 脚本与微服务中一律使用异步版本,避免阻塞线程池。
  2. 面向接口编程。使用 IChameleonDbContext 接口上的方法;GetQuerySql / ExecuteDataTable 只在实现类 ChameleonDbContext 上提供,接口上没有,如需使用必须注入具体类。
  3. 字段名一律小写。ObjectData 的键与查询字段名最终都会转为小写写入 SQL(如 createdtime、isdeleted),建议代码中直接使用小写字段编码。
  4. 对象编码即表名来源。metaObjectCode 中的 . 会转换为 _ 并整体转小写,如 "User.Information" 对应表 user_information;不要自己拼接表名。
  5. 查询不会自动过滤已逻辑删除的数据。isdeleted = true 的数据仍会出现在查询结果中,需要排除时必须在过滤条件中显式加 FilterBuilder.Eq("isdeleted", false)。
  6. 不要手动设置审计字段。createdby / createdtime / modifiedby / modifiedtime / organization / isdeleted 由平台自动填充(已有值则不覆盖)。
  7. 调用前确保上下文有效。当前请求上下文(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);

下一步​

相关实现​

  • 接口定义:chameleon-core/components/Chameleon.Database/DbContext/IChameleonDbContext.cs
  • 实现:chameleon-core/components/Chameleon.Database/DbContext/ChameleonDbContext.cs(含 *Operation.cs / *OperationAsync.cs / SqlOperation.cs 分部类)
  • 过滤构建:chameleon-core/components/Chameleon.Database/FilterBuilder.cs、DynamicFilterExtension.cs
  • SDK 挂载点:chameleon/server/Components/Chameleon.SDK/ChameleonSDK.cs 的 DbContext 属性