当前位置: 首页 > news >正文

AI 工程化实战:分钟带你快速掌握 Function Calling!

一、简化查询

1. 先看一下查询的例子

///

/// 账户获取服务

///

///

///

public class AccountGetService(AccountTable table, IShadowBuilder builder)

{

private readonly SqlSource _source = new(builder.DataSource);

private readonly IParamQuery _accountQuery

= builder.BuildResult(

table.ToQuery()

.And(account => account.Id.Equal())

.ToSelect()

.SelectSelfColumns()

);

///

/// 获取账户

///

///

///

///

public Task GetAsync(Account param, CancellationToken token = default)

=> _accountQuery.GetFirstAsync(_source, param, token);

}

2. 调用方式如下

var account = await accountGetService.GetAsync(new Account { Id = 1L });

3. 这个例子我们可以简化一下

参数直接使用Id(类型由Account简化为long)

很大一部分数据库操作都只有一个参数(GetById、GetByName等)

为此定义一个含单个属性类有点浪费

按上面的例子使用实体类作为参数也感觉怪怪的

DBShadow.net支持这种简化操作

单个参数无需封装,直接使用参数类型即可

public class AccountGetService(AccountTable table, IShadowBuilder builder)

{

private readonly SqlSource _source = new(builder.DataSource);

private readonly IParamQuery _accountQuery

= builder.BuildResult(

table.ToQuery()

.And(account => account.Id.Equal())

.ToSelect()

.SelectSelfColumns()

);

public Task GetAsync(long accountId, CancellationToken token = default)

=> _accountQuery.GetFirstAsync(_source, param, token);

}

var account = await accountGetService.GetAsync(1L);

4. 特别注意不要在Dapper中这样使用

Dapper是不支持这种简化操作

以下Dapper错误示例会抛出异常

System.InvalidOperationException:“Must add values for the following parameters: @Id”

await using var conn = _dataSource.CreateConnection();

var sql = "SELECT \"Id\",\"Title\",\"Content\",\"Done\",\"LastTime\" FROM \"Todo\" WHERE \"Id\"=@Id";

var first = await conn.QueryFirstOrDefaultAsync(sql, 1L);

二、 集合参数也支持简化操作

1. IN查询简化的例子

In的参数名是可选和前面例子的Equal是一样的,默认字段名

In查询的实参支持数组、集合及字典

只有In一个集合参数时支持直接传数组、集合或字典

这时参数名(eg: AccountIds)就无所谓取什么名了

因为不需要按参数名反射获取属性了

///

/// 批量账户获取服务

///

///

///

public class AccountBatchService(AccountTable table, IShadowBuilder builder)

{

private readonly SqlSource _source = new(builder.DataSource);

private readonly IParamQuery _accountQuery

= builder.BuildResult(

table.ToQuery()

.And(account => account.Id.In("AccountIds"))

.ToSelect()

.SelectSelfColumns()

);

///

/// 批量获取账户

///

///

///

///

public IAsyncEnumerable GetAsync(long[] accountIds, CancellationToken token = default)

=> _accountQuery.QueryAsync(_source, accountIds, token);

}

2. 以上调用的例子如下

[Fact]

public async Task Batch()

{

var count = 0;

var service = new AccountBatchService(table, builder);

var list = service.GetAsync([1L, 2L, 3L]);

await foreach (var item in list)

{

_output.WriteLine($"{item.Id}:{item.Amount}");

count++;

}

Assert.Equal(3, count);

}

// 1:100

// 2:200

// 3:300

三、泛型查询

1. 泛型服务类代码

该服务用来按字段Id查询表Account

参数TParam是泛型,这样可以直接使用DTO参数来查询,减少类型转化的开销

返回值TAccount也是泛型,这样就可以直接返回视图模型或者领域模型

这样的泛型服务类就非常的通用

///

/// 账户获取泛型服务

///

///

///

public class AccountGetService(AccountTable table, IShadowBuilder builder)

{

private readonly SqlSource _source = new(builder.DataSource);

private readonly IParamQuery _accountQuery

= builder.BuildResult(

table.ToQuery()

.And(account => account.Id.Equal())

.ToSelect()

.SelectSelfColumns()

);

///

/// 获取账户

///

///

///

///

public Task GetAsync(TParam param, CancellationToken token = default)

=> _accountQuery.GetFirstAsync(_source, param, token);

}

2. 中规中矩的调用方式

var service = new AccountGetService(_table, _builder);

var account = await service.GetAsync(new Account { Id = 1L });

Assert.NotNull(account);

3. 支持简单调用方式

var service = new AccountGetService(_table, _builder);

var account = await service.GetAsync(1L);

Assert.NotNull(account);

四、总结

DBShadow.net预编译比较智能

只有1个参数时支持化繁为简,支持直接传值做为参数值

这样可以节约定义只有一个属性的参数类

参数和返回值类型还可以定义为泛型,可以做到更加灵活薪庞贝县

http://www.jsqmd.com/news/684262/

相关文章:

  • 生成式AI如何革新汽车软件测试?
  • go: Observer Pattern
  • # 用AI写代码的人越来越多,但能判断AI对不对的人没多几个
  • 流量来了接不住 才是很多跨境卖家真正的难题
  • 别再死磕AT模式了!用Seata TCC模式搞定高并发库存扣减(Spring Cloud Alibaba实战)
  • 最危险的不是刺头,而是“模范员工“
  • 不教而战,边学边教:大模型在线策略蒸馏的机制、优势与挑战
  • 并发编程专题(一)
  • 周薪近3万!Anthropic“重金”挖科学家,只为给AI“纠偏”
  • 如何3分钟掌握安卓虚拟定位:FakeLocation的终极隐私保护指南
  • 别再死记硬背了!用C++ TinyWebServer项目,一次性搞懂Reactor和Proactor模式的区别
  • Python实现移动平均平滑技术的时间序列分析
  • 我做了一个花粉星球:把风、花粉与地球写成一封浪漫的情书
  • 手把手教你配置RK3588单/双PMIC方案,避免烧芯片的坑(附完整DTS代码)
  • ChatGPT Images 2.0让AI设计离“靠谱”只剩一步!
  • Docker镜像体积暴增300%的真相(工业级精简指南:从2.4GB到87MB实录)
  • SPSSAU调节作用怎么做:软件操作步骤与结果指标解读
  • 【maaath】Flutter for OpenHarmony 跨平台工程日志能力实战:分级日志输出与本地文件持久化
  • 抖音批量下载终极指南:三分钟搞定无水印视频采集
  • python基础03基本数据类型
  • 深入理解 MCP (Model Context Protocol):开启 AI Agent 交互新时代
  • cocos小游戏的打包与发布
  • 告别版本地狱:用Anaconda为你的RTX 3060/3070/3080显卡创建独立的TensorFlow 2.4.0虚拟环境
  • 告别硬件烧录!用RT-Thread Simulator在Visual Studio 2022上快速调试LVGL界面
  • Python动态特性与Monkey Patching实战解析
  • 一站式开源解决方案:douyin-downloader 革命性解决抖音内容批量下载与智能管理难题
  • 结构体进阶
  • 解放你的QQ音乐收藏:QMCDecode轻松解密加密音频格式
  • Pandas数据过滤与聚合:深入分析Uber纽约出行数据
  • AI UX范式正在悄然崩塌:从“命令执行”到“意图发现”的60年未有之大迁徙