Tencent.CloudBase
1.0.1
dotnet add package Tencent.CloudBase --version 1.0.1
NuGet\Install-Package Tencent.CloudBase -Version 1.0.1
<PackageReference Include="Tencent.CloudBase" Version="1.0.1" />
<PackageVersion Include="Tencent.CloudBase" Version="1.0.1" />
<PackageReference Include="Tencent.CloudBase" />
paket add Tencent.CloudBase --version 1.0.1
#r "nuget: Tencent.CloudBase, 1.0.1"
#:package Tencent.CloudBase@1.0.1
#addin nuget:?package=Tencent.CloudBase&version=1.0.1
#tool nuget:?package=Tencent.CloudBase&version=1.0.1
CloudBase C# SDK
腾讯云开发(Tencent CloudBase)C# SDK。适用于 .NET 控制台、服务端、桌面,以及 Unity、Godot、MAUI、Blazor 等多种 C# 运行环境。
- 在线文档:https://docs.cloudbase.net/api-reference/csharp
- 发布形态:两条同源同版本的分发线,按宿主择一即可——
- NuGet 包
Tencent.CloudBase:面向通用 .NET 项目(控制台、服务端、MAUI、Blazor、Godot、Xamarin 等)。 - Unity UPM 包
com.tencent.cloudbase:面向 Unity 工程,通过 Git URL 一步安装,预编译多平台 DLL + 自带 Unity 适配层,全平台(含 WebGL)即装即用。
- NuGet 包
- 目标框架:
netstandard2.1(供 Unity / Godot / Xamarin / 旧版 .NET 消费)与net10.0(供现代 .NET 消费)双目标,同装在 NuGet 包内。 - 依赖:
netstandard2.1使用内置零依赖 JSON 实现(Internal/LiteJson),无任何第三方依赖,Unity 只需单个CloudBase.dll;net10.0仅用运行时自带的System.Text.Json,另按目标框架条件引用 DI 相关扩展。 - 网络层可插拔:内核只依赖平台无关的
IHttpTransport抽象,默认实现HttpClientTransport(基于System.Net.Http),在不支持System.Net.Http的环境(如 Unity WebGL)可注入自定义传输。
功能模块
| 模块 | 入口 | 说明 |
|---|---|---|
| 认证 | app.Auth |
匿名登录、密码/用户名登录、验证码 OTP、OAuth、自定义登录票据、用户管理、会话刷新等 |
| 验证码 | app.Captcha |
图形/行为验证码获取与校验(回调式,无 UI 依赖) |
| 云函数 | app.Functions / app.CallFunctionAsync |
调用云函数(含云托管函数) |
| 云托管 | app.CloudRun / app.CallContainerAsync |
调用云托管容器服务 |
| API 网关 | app.Apis |
通过 API 网关调用 HTTP 接口 |
| MySQL | app.MySql |
基于 PostgREST 风格的 MySQL RESTful 读写 |
| 文档数据库 | app.Database() |
文档型(NoSQL)数据库 CRUD、聚合、事务、原生命令 |
| 数据模型 | app.Models |
数据模型 CRUD、聚合、数据源查询 |
| 云存储 | app.Storage |
文件上传、下载、签名 URL、删除、复制、移动 |
安装
.NET 项目(推荐,NuGet)
dotnet add package Tencent.CloudBase
或在 .csproj 中:
<ItemGroup>
<PackageReference Include="Tencent.CloudBase" Version="1.0.0" />
</ItemGroup>
自动选用 net10.0 目标(含 DI 集成)。
Unity 项目(推荐,UPM Git URL 一步安装)
在 Unity 中打开 Window → Package Manager → +(左上角)→ Add package from git URL...,粘贴:
https://github.com/TencentCloudBase/cloudbase-csharp-sdk.git?path=unity/com.tencent.cloudbase#v1.0.0
无需任何外部工具,自带 Unity 适配层,全平台(含 WebGL)即装即用。其它引入方式(NuGetForUnity、预编译 DLL)详见下方 引入方式(Unity)。
从源码引用(本地开发 / 贡献)
# 构建 SDK
dotnet build src/CloudBase/CloudBase.csproj
# 或构建整个解决方案(含示例)
dotnet build CloudBase.sln
<ItemGroup>
<ProjectReference Include="path/to/src/CloudBase/CloudBase.csproj" />
</ItemGroup>
快速上手
using CloudBase;
using HttpMethod = CloudBase.HttpMethod;
using CloudBaseApp = CloudBase.CloudBase;
// 初始化
var app = await CloudBaseApp.InitAsync(
env: "your-env-id",
region: "ap-shanghai",
accessKey: "your-publishable-key"); // 可选,用于匿名访问
// 匿名登录
var res = await app.Auth.SignInAnonymouslyAsync();
if (res.IsSuccess)
{
Console.WriteLine($"uid = {res.Data?.User?.Uid}");
}
完整示例见 examples/QuickStart/Program.cs:
export CLOUDBASE_ENV=your-env-id
export CLOUDBASE_ACCESS_KEY=your-publishable-key
dotnet run --project examples/QuickStart
可视化测试工具
项目提供了基于 Spectre.Console 的交互式终端测试界面:
dotnet run --project examples/TerminalUI
该工具提供交互式菜单,支持以下操作:
| 选项 | 操作 |
|---|---|
| 1 | 初始化 CloudBase |
| 2 | 匿名登录 |
| 3 | 退出登录 |
| 4 | 获取当前用户 |
| 5 | 调用云函数 |
| 6 | 查询数据模型 |
| 7 | 查询 MySQL |
| 8 | 云存储上传 |
| 0 | 退出 |
跨平台与多场景接入
SDK 以「平台无关内核 + 可插拔适配器」的方式设计,两个可插拔点:
- 存储适配
IKeyValueStore:持久化会话、Device ID、验证码 Token 等。默认FileKeyValueStore(桌面/服务端),另有InMemoryKeyValueStore(测试)。 - 网络适配
IHttpTransport:默认HttpClientTransport(基于System.Net.Http);不支持该栈的环境可自定义。
| 场景 | 目标框架 | 存储适配 | 网络适配 |
|---|---|---|---|
| 控制台 / 服务端 / ASP.NET Core | net10.0 |
FileKeyValueStore(默认) |
HttpClientTransport(默认) |
| .NET MAUI / WPF / WinForms | net10.0 |
自定义(如加密存储)或默认 | 默认 |
| Blazor Server | net10.0 |
默认 | 默认 |
| Unity(PC / Android / iOS) | netstandard2.1 |
必须注入 PlayerPrefs 版实现 |
默认(Mono/IL2CPP 支持 HttpClient) |
| Unity WebGL | netstandard2.1 |
PlayerPrefs 版实现 |
必须注入 UnityWebRequest 版 IHttpTransport |
| Godot(C#) | netstandard2.1 |
自定义(如基于 user://) |
默认或基于 HttpRequest 的实现 |
引入方式(Unity)
推荐:UPM Git URL 一步安装(无需任何外部工具,自带适配层,全平台含 WebGL)
仓库维护了一个 预编译多平台 DLL(多平台模式) 的 UPM 包 unity/com.tencent.cloudbase,Runtime/Plugins/ 下含两份按平台自动加载的 CloudBase.dll(Standard/ 含 System.Net.Http 供 Editor/Standalone/iOS/Android,WebGL/ 剔除 System.Net.Http 仅 WebGL),加上源码形式的 Unity 适配层 + link.xml,装完即用。
在 Unity 中打开 Window → Package Manager → +(左上角)→ Add package from git URL...,粘贴:
https://github.com/TencentCloudBase/cloudbase-csharp-sdk.git?path=unity/com.tencent.cloudbase#v1.0.0
把地址替换为你实际发布的仓库地址;
#v1.0.0用于锁定版本(省略则取默认分支最新)。
安装后一行式初始化(自动适配平台,含 WebGL):
using CloudBaseGame;
var app = await CloudBaseUnity.InitAsync(env: "your-env-id");
// 自动注入 PlayerPrefs 存储;WebGL 自动切 UnityWebRequest 传输,其他平台用 HttpClient。
备选一:NuGetForUnity(与 .NET 共用同一个 NuGet 包)
- 安装 NuGetForUnity(
Add package from git URL→https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity)。 NuGet → Manage NuGet Packages,搜索Tencent.CloudBase并安装(自动选netstandard2.1)。
注意:NuGet 包只含核心 SDK,适配层(CloudBaseUnity 等)需从 UPM 包 unity/com.tencent.cloudbase/Runtime 复制。
备选二:预编译 DLL
执行 dotnet build src/CloudBase -c Release -f netstandard2.1(或 ./scripts/publish.sh unity <你的工程>/Assets/Plugins/CloudBase),将 bin/Release/netstandard2.1/CloudBase.dll 放入 Assets/Plugins(零第三方依赖,单 DLL 即可),适配层同样需从 UPM 包 unity/com.tencent.cloudbase/Runtime 复制。
Unity 完整示例(存储适配、主线程调度、登录、数据集合、图片操作)见 examples/UnityGame/。
注入自定义适配器示例
// 注入自定义存储 + 自定义网络传输(如 Unity WebGL)
var app = await CloudBase.CloudBase.InitAsync(
env: "your-env-id",
store: new MyPlayerPrefsStore(), // 实现 IKeyValueStore
transport: new UnityWebRequestTransport() // 实现 IHttpTransport
);
IHttpTransport只需实现Task<HttpTransportResponse> SendAsync(HttpTransportRequest request, CancellationToken ct): 入参为平台无关的方法/URL/头/字节体,返回状态码/头/字节体,不涉及任何System.Net.Http类型,因此可用UnityWebRequest等任意网络栈实现。
初始化参数
CloudBase.InitAsync 参数说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
env |
string |
必填 | TCB 环境 ID |
region |
string |
ap-shanghai |
地域 |
lang |
string |
zh-CN |
语言 |
accessKey |
string? |
null |
Publishable Key,用于匿名访问 |
authConfig |
AuthConfig? |
null |
认证配置 |
captchaConfig |
CaptchaConfig? |
null |
验证码配置 |
store |
IKeyValueStore? |
FileKeyValueStore |
键值存储(持久化会话、Device ID);Unity/移动端应注入平台实现 |
httpClient |
HttpClient? |
null |
自定义 System.Net.Http.HttpClient(会被包装为 HttpClientTransport) |
transport |
IHttpTransport? |
null |
自定义 HTTP 传输;用于 WebGL 等不支持 System.Net.Http 的环境,优先级高于 httpClient |
intl |
bool |
false |
是否国际站,为 true 时使用国际站域名 |
retryOptions |
RetryOptions? |
null |
HTTP 重试退避策略;null 时使用默认策略(对超时/连接失败/429/5xx 指数退避重试,最多 2 次)。传入 RetryOptions.Disabled 可关闭 |
concurrencyOptions |
ConcurrencyOptions? |
null |
客户端并发限流策略;null 时不限流。高并发服务端可设置上限避免打满连接池 / 过载后端 |
BaseUrl 规则:
intl=true使用https://{env}.api.intl.tcloudbasegateway.com,否则为https://{env}.api.tcloudbasegateway.com。
网络可靠性:重试、限流与连接池
重试退避(RetryOptions)
SDK 对幂等且瞬时失败的请求(网络超时、连接失败、429、5xx)执行**指数退避 + 抖动(jitter)**的自动重试,提升弱网 / 服务端抖动下的可用性。认证类错误(401/token 过期)由认证模块单独处理,429 之外的 4xx 业务错误不重试。
var app = await CloudBase.InitAsync(
env: "your-env",
retryOptions: new RetryOptions
{
MaxRetries = 3, // 最大重试次数(不含首发),默认 2
BaseDelay = TimeSpan.FromMilliseconds(200), // 基础退避,第 n 次重试基准为 BaseDelay * 2^(n-1)
MaxDelay = TimeSpan.FromSeconds(5), // 单次退避上限
UseJitter = true, // 全抖动,分散重试时刻避免惊群
RespectRetryAfter = true, // 遵循服务端 Retry-After 头(429/503)
});
// 关闭重试
var app2 = await CloudBase.InitAsync(env: "your-env", retryOptions: RetryOptions.Disabled);
| 参数 | 默认值 | 说明 |
|---|---|---|
MaxRetries |
2 |
最大重试次数(不含首次请求),设为 0 关闭 |
BaseDelay |
200ms |
指数退避基础延时 |
MaxDelay |
5s |
单次重试延时上限 |
UseJitter |
true |
是否叠加随机抖动,避免大量客户端同刻集体重试 |
RespectRetryAfter |
true |
是否遵循 Retry-After 响应头(在 MaxDelay 内) |
RetryableStatusCodes |
408,429,500,502,503,504 |
触发重试的状态码集合 |
并发限流(ConcurrencyOptions)
限制单个客户端同时在途(in-flight)的 HTTP 请求数,起到客户端侧「限流阀」的作用,避免瞬间打满连接池 / socket 或对后端过载。这是一种协作式背压:超过上限的请求异步等待信号量,而非直接失败;也可设置 AcquireTimeout 让长时间无法获取额度的请求快速失败(fail-fast)。
var app = await CloudBase.InitAsync(
env: "your-env",
concurrencyOptions: new ConcurrencyOptions
{
MaxConcurrentRequests = 64, // 最大并发在途请求数,0 表示不限流
AcquireTimeout = TimeSpan.FromSeconds(5), // 获取额度的最长等待,超时抛 CloudBaseNetworkException
});
HttpClient 连接池调优
默认的 HttpClientTransport 在内部自建 HttpClient 时使用运行时默认的连接池配置,适用于大多数场景。对于长驻服务端进程 / 手动持有单例的高并发场景,建议使用预调优的连接池工厂或注入自定义 HttpClient:
// 方式一:使用 SDK 提供的预调优传输工厂(net6+,基于 SocketsHttpHandler)
var transport = HttpClientTransport.CreatePooled(
timeout: TimeSpan.FromSeconds(30),
maxConnectionsPerServer: 64, // 每目标主机最大并发连接数,防 socket 耗尽
pooledConnectionLifetime: TimeSpan.FromMinutes(2), // 连接最长存活,定期回收以感知 DNS 变更
pooledConnectionIdleTimeout: TimeSpan.FromSeconds(90));
var app = await CloudBase.InitAsync(env: "your-env", transport: transport);
// 方式二:注入自定义 HttpClient(自行管理 SocketsHttpHandler)
var handler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(2),
MaxConnectionsPerServer = 64,
EnableMultipleHttp2Connections = true,
};
var httpClient = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) };
var app2 = await CloudBase.InitAsync(env: "your-env", httpClient: httpClient);
关键点
- 不要为每次请求创建新的
HttpClient(会耗尽 socket);也不要无限期复用单个HttpClient而不设PooledConnectionLifetime(无法感知 DNS 变更)。- ASP.NET Core / DI 场景:优先使用
IHttpClientFactory统一管理连接池,此时无需CreatePooled——通过AddCloudBase传入由 factory 创建的HttpClient即可。MaxConnectionsPerServer应与ConcurrencyOptions.MaxConcurrentRequests协调设置,避免限流阈值高于连接池上限导致排队。
认证 (app.Auth)
// 匿名登录
await app.Auth.SignInAnonymouslyAsync();
// 用户名 + 密码
var req = new SignInWithPasswordReq("password") { Username = "alice" };
await app.Auth.SignInWithPasswordAsync(req);
// 邮箱/手机验证码登录(OTP)
var otp = await app.Auth.SignInWithOtpAsync(new SignInWithOtpReq { Email = "a@b.com" });
// 收到验证码后回填完成登录
await otp.Data!.VerifyOtp!(new VerifyOtpParams("123456"));
// 获取 / 刷新用户信息
var user = await app.Auth.GetUserAsync();
// 会话管理
await app.Auth.RefreshSessionAsync();
await app.Auth.SignOutAsync();
其它能力:SignUpAsync、SignInWithOtpAsync、SignInWithOAuthAsync、SignInWithIdTokenAsync、
SignInWithCustomTicketAsync、UpdateUserAsync、DeleteUserAsync、LinkIdentityAsync、
ResetPasswordForEmailAsync、ReauthenticateAsync、GetClaimsAsync 等。
所有方法返回 CloudBaseResponse<T>,通过 IsSuccess / Data / Error 判断结果。
验证码 (CaptchaConfig)
非 UI 环境通过回调获取验证码 token:
var app = await CloudBaseApp.InitAsync(
env: "your-env-id",
captchaConfig: new CaptchaConfig
{
OnCaptchaRequired = async (captchaData) =>
{
// captchaData 为需要展示给用户的验证数据
// 返回用户完成验证后得到的 token
return await GetTokenFromUserAsync(captchaData);
},
});
云函数与云托管
// 云函数
var fn = await app.CallFunctionAsync(
name: "hello",
data: new Dictionary<string, object?> { ["msg"] = "world" });
// 云托管
var run = await app.CallContainerAsync(
name: "my-service",
method: HttpMethod.Get,
path: "/api/hello");
MySQL (app.MySql)
采用 PostgREST 风格的链式查询构建器。入口 app.MySql.From(table) 取得查询构建器;
如需指定实例/数据库用 app.MySql.Rdb(instance, database).From(table)。
构建器实现了 GetAwaiter(),可直接 await。
// 查询:select() + 过滤器 + 修饰符
var q = await app.MySql.From("articles")
.Select("id, title, created_at", new MySqlSelectOptions { Count = "exact" })
.Gt("id", 2)
.Like("title", "%cloudbase%")
.Order("created_at", ascending: false)
.Limit(10);
Console.WriteLine($"{q.Data.Count} 行,总数 {q.Total}");
// 仅取总数(head + count)
var head = await app.MySql.From("articles")
.Select("*", new MySqlSelectOptions { Count = "exact", Head = true });
Console.WriteLine(head.Total);
// 单条对象
var one = await app.MySql.From("articles").Select().Eq("id", 1).Single();
// 插入(可 .Select() 返回插入行);批量传数组
await app.MySql.From("articles").Insert(new { title = "New", content = "..." });
await app.MySql.From("articles").Insert(new[]
{
new { title = "A" },
new { title = "B" },
});
// 更新(需配合过滤器定位行)
await app.MySql.From("articles").Update(new { title = "新标题" }).Eq("id", 1);
// 删除(需配合过滤器定位行)
await app.MySql.From("articles").Delete().In("id", new[] { 1, 2, 3 });
// Upsert(可指定冲突列)
await app.MySql.From("articles")
.Upsert(new { id = 42, title = "unique" }, new MySqlUpsertOptions { OnConflict = "title" });
所有操作返回 MySqlResponse,通过 IsSuccess / Data / Total / Code / Message 读取结果。
- 过滤器:
Eq、Neq、Gt、Gte、Lt、Lte、Like、Is、In、Match、Not、Or、Filter - 修饰符:
Order、Limit、Range、Single、MaybeSingle、以及写操作后的Select(返回受影响行)
兼容说明:旧的扁平方法
QueryAsync/InsertAsync/UpdateAsync/DeleteAsync/CountAsync仍然保留,但推荐使用上述链式写法。
文档数据库 (app.Database())
文档型(NoSQL)数据库,提供链式(fluent)调用风格,基于 MongoDB 风格的 RESTful HTTP API。
入口 app.Database() 使用默认实例/数据库((default)),也可 app.Database("instance", "database") 指定。
var db = app.Database();
var _ = db.Command; // 查询/更新操作符
// 新增:单个对象 -> Id;对象集合 -> Ids
var add = await db.Collection("todos").Add(new { title = "学习 CloudBase", completed = false });
var addMany = await db.Collection("todos").Add(new[]
{
new { title = "任务一", completed = false },
new { title = "任务二", completed = true },
});
// 条件查询(where + 操作符)+ 排序 + 分页
var q = await db.Collection("todos")
.Where(new Dictionary<string, object?> { ["age"] = _.Gte(18) })
.OrderBy("age", "desc")
.Skip(0)
.Limit(10)
.Get();
foreach (var doc in q.Data) { /* ... */ }
// 按 _id 查询单个文档
var one = await db.Collection("todos").Doc(add.Id!).Get();
// 统计 / 单文档更新 / 条件删除
var count = await db.Collection("todos").Where(new { completed = false }).Count();
var upd = await db.Collection("todos").Doc(add.Id!).Update(new
{
completed = true,
viewCount = _.Inc(1), // 操作符:自增;普通字段自动归入 $set
});
var del = await db.Collection("todos").Where(new { completed = true }).Remove();
// 完全替换 / 更新或创建(set,不存在则 upsert)
await db.Collection("todos").Doc("custom-id").Set(new { title = "新任务", completed = false });
// 聚合查询(链式阶段 + End)
var agg = await db.Collection("todos")
.Aggregate()
.Match(new Dictionary<string, object?> { ["age"] = _.Gte(18) })
.Group(new Dictionary<string, object?> { ["_id"] = "$priority", ["count"] = new Dictionary<string, object?> { ["$sum"] = 1 } })
.Sort(new { count = -1 })
.End();
// 事务:开启 -> 事务内操作 -> 提交/回滚
var transaction = await db.StartTransactionAsync();
await transaction.Collection("todos").Add(new { title = "事务任务" });
await transaction.CommitAsync(); // 或 transaction.RollbackAsync()
// 创建集合 / 执行 MongoDB 原生命令
await db.CreateCollectionAsync("logs");
var cmd = await db.RunCommandsAsync(new object[]
{
new { find = "todos", filter = new Dictionary<string, object?> { ["age"] = _.Gte(18) }, limit = 10 },
});
链式 API 一览:
| 调用 | 说明 |
|---|---|
db.Collection(name) |
取集合引用 |
.Where(cond) / .OrderBy(f, dir) / .Limit(n) / .Skip(n) / .Field(p) |
查询条件 / 排序 / 分页 / 字段投影 |
.Get() / .Count() / .Update(d) / .Remove() |
查询 / 计数 / 按条件更新 / 按条件删除 |
.Add(data) |
新增(单对象或集合,自动区分单条/批量) |
.Doc(id).Get()/.Set()/.Update()/.Remove() |
单文档读取 / 覆盖写入 / 局部更新 / 删除 |
.Aggregate().Match().Group().Sort().End() |
聚合查询 |
db.Command (_.Gt / _.In / _.Inc / _.Push …) |
查询/更新操作符 |
db.CreateCollectionAsync(name) |
创建集合 |
db.StartTransactionAsync() → transaction.Collection()/.CommitAsync()/.RollbackAsync() |
事务 |
db.RunCommandsAsync(commands, transactionId) |
执行 MongoDB 原生命令 |
db.RegExp(regexp, options) |
构造正则条件 |
更新数据说明:
Update中普通字段会自动归入$set,操作符(_.Inc/_.Push/_.Remove等)按 MongoDB 语义归组;Set则完全替换文档且不存在时自动创建。
响应统一继承 DbResponse,通过 IsSuccess / Code / Message / RequestId / StatusCode 读取;查询结果读 Data(文档列表)。响应体中的
Strict EJSON(如 {"$oid":...}、{"$numberInt":...}、{"$date":...})会自动还原为普通 C# 值。
数据模型 (app.Models)
按模型名取得操作句柄 app.Models["modelName"],再调用对应的 MethodAsync(...):
// 取得绑定模型名的操作句柄
var article = app.Models["article"]; // 或 app.Models.Model("article")
// 单条查询
var one = await article.GetAsync(
filter: new Dictionary<string, object?>
{
["where"] = new Dictionary<string, object?> { ["_id"] = new Dictionary<string, object?> { ["$eq"] = "recordId" } },
},
select: new Dictionary<string, object?> { ["$master"] = true });
// 多条查询
var list = await article.ListAsync(pageSize: 10, pageNumber: 1, getCount: true);
Console.WriteLine($"{list.Records.Count} / {list.Total}");
// 创建
await article.CreateAsync(new Dictionary<string, object?> { ["title"] = "Hello" });
// 更新
await article.UpdateAsync(
filter: new Dictionary<string, object?>
{
["where"] = new Dictionary<string, object?> { ["_id"] = new Dictionary<string, object?> { ["$eq"] = "xxx" } },
},
data: new Dictionary<string, object?> { ["title"] = "New" });
// 按 ID 删除
await article.DeleteByIdAsync("recordId");
可用方法:GetAsync、GetByIdAsync、ListAsync、CreateAsync、CreateManyAsync、
UpdateAsync、UpdateManyAsync、UpsertAsync、DeleteAsync、DeleteByIdAsync、DeleteManyAsync。
数据源相关能力仍在 app.Models 上:GetAggregateDataSourceListAsync、
GetDataSourceAggregateDetailAsync、GetBasicDataSourceListAsync、GetSchemaListAsync、
MysqlCommandAsync 等。
云存储 (app.Storage)
先通过 app.Storage.From() 取得文件操作客户端,再调用具体方法。
// 取得文件操作客户端
var storage = app.Storage.From();
// 上传
var bytes = File.ReadAllBytes("photo.jpg");
var up = await storage.UploadAsync("images/photo.jpg", bytes,
new StorageUploadOptions { ContentType = "image/jpeg" });
Console.WriteLine(up.Data?.Id);
// 覆盖更新(等同 upsert)
await storage.UpdateAsync("images/photo.jpg", bytes);
// 下载 URL / 签名 URL / 公有 URL / 下载字节
var urls = await storage.GetDownloadUrlsAsync(new List<string> { up.Data!.Id! });
var signed = await storage.CreateSignedUrlAsync(up.Data!.Id!, expiresIn: 3600);
var publicUrl = await storage.GetPublicUrlAsync("images/photo.jpg");
var data = await storage.DownloadAsync(up.Data!.Id!);
// 元信息 / 是否存在
var info = await storage.InfoAsync("images/photo.jpg");
var exists = await storage.ExistsAsync("images/photo.jpg");
// 删除 / 复制 / 移动
await storage.RemoveAsync(new List<string> { "cloud://..." });
await storage.CopyAsync("a.txt", "b.txt");
await storage.MoveAsync("a.txt", "c.txt");
// 链式:失败即抛出 StorageException
await app.Storage.From().ThrowOnError().InfoAsync("cloud://not-exist/none.txt");
完整 API 参考
以下列出各模块所有可调用的公开方法。所有异步方法均以 Async 结尾(.NET TAP 约定),需配合 await 使用。
顶层入口 (CloudBase)
| 成员 | 签名 | 说明 |
|---|---|---|
InitAsync |
static Task<CloudBase> InitAsync(string env, string region="ap-shanghai", string lang="zh-CN", string? accessKey=null, AuthConfig? authConfig=null, CaptchaConfig? captchaConfig=null, IKeyValueStore? store=null, HttpClient? httpClient=null, IHttpTransport? transport=null, bool intl=false, RetryOptions? retryOptions=null, ConcurrencyOptions? concurrencyOptions=null) |
初始化应用实例(transport 优先级高于 httpClient;retryOptions/concurrencyOptions 控制重试与限流,见「网络可靠性」章节) |
CallFunctionAsync |
Task<FunctionResponse> CallFunctionAsync(string name, FunctionType type=Function, IDictionary<string,object?>? data=null, HttpMethod method=Post, string path="/", IDictionary<string,string>? header=null, bool parse=true) |
调用云函数(快捷方式) |
CallContainerAsync |
Task<CloudRunResponse> CallContainerAsync(string name, HttpMethod method=Get, string path="/", IDictionary<string,string>? header=null, IDictionary<string,object?>? data=null) |
调用云托管(快捷方式) |
Database |
CloudBaseDb Database(string? instance=null, string? database=null) |
获取文档数据库操作入口 |
| 属性 | Auth / Captcha / CloudRun / Functions / Apis / MySql / Models / Storage / Config / HttpClient |
各模块入口 |
认证 (app.Auth)
所有方法返回 Task<CloudBaseResponse<T>>(除标注外)。
| 方法 | 签名 |
|---|---|
SignInAnonymouslyAsync |
(string? providerToken=null) |
SignInWithPasswordAsync |
(SignInWithPasswordReq @params) |
SignInWithUsernameAsync |
(string username, string password) |
SignInWithOtpAsync |
(SignInWithOtpReq @params) |
SignInWithOAuthAsync |
(SignInWithOAuthReq @params) |
SignInWithIdTokenAsync |
(SignInWithIdTokenReq @params) |
SignInWithCustomTicketAsync |
(Func<Task<string>> getTicketFn) |
SignUpAsync |
(SignUpReq @params) |
GetVerificationAsync |
(string? email=null, string? phoneNumber=null) |
VerifyAsync |
(string verificationId, string verificationCode) |
VerifyOtpAsync |
(VerifyOtpReq @params) |
VerifyOAuthAsync |
(VerifyOAuthReq? @params=null) |
ResendAsync |
(ResendReq @params) |
GetSessionAsync |
() |
RefreshSessionAsync |
(string? refreshToken=null) |
SetSessionAsync |
(SetSessionReq @params) |
SignOutAsync |
(SignOutReq? @params=null) |
GetUserAsync |
() |
RefreshUserAsync |
() |
UpdateUserAsync |
(UpdateUserReq @params) |
DeleteUserAsync |
(DeleteUserReq @params) |
GetUserIdentitiesAsync |
() |
LinkIdentityAsync |
(LinkIdentityReq @params) |
UnlinkIdentityAsync |
(UnlinkIdentityReq @params) |
ResetPasswordForEmailAsync |
(string emailOrPhone, string? redirectTo=null) |
ResetPasswordForOldAsync |
(ResetPasswordForOldReq @params) |
ReauthenticateAsync |
() |
GetClaimsAsync |
() |
OnAuthStateChange |
CloudBaseResponse<OnAuthStateChangeResultData> OnAuthStateChange(OnAuthStateChangeCallback callback)(同步,返回可取消订阅) |
验证码 (app.Captcha)
| 方法 | 签名 |
|---|---|
CreateCaptchaDataAsync |
Task<CreateCaptchaDataRes> (string state) |
VerifyCaptchaDataAsync |
Task<VerifyCaptchaRes> (string token, string key) |
GetCaptchaTokenAsync |
Task<string?> (bool forceNew=false, string state="") |
AppendCaptchaTokenToUrlAsync |
Task<string> (string url, string state, bool forceNew=false) |
FindCaptchaTokenAsync |
Task<string?> () |
ClearCaptchaTokenAsync |
Task () |
云函数 (app.Functions)
| 方法 | 签名 |
|---|---|
CallFunctionAsync |
Task<FunctionResponse> (string name, FunctionType type=Function, IDictionary<string,object?>? data=null, HttpMethod method=Post, string path="/", IDictionary<string,string>? header=null, bool parse=true) |
CallRealFunctionAsync |
Task<FunctionResponse> (string name, IDictionary<string,object?>? data, bool parse=true) |
CallCloudRunFunctionAsync |
Task<FunctionResponse> (string name, HttpMethod method, string path, IDictionary<string,string>? header, IDictionary<string,object?>? data) |
云托管 (app.CloudRun)
| 方法 | 签名 |
|---|---|
CallContainerAsync |
Task<CloudRunResponse> (string name, HttpMethod method=Get, string path="/", IDictionary<string,string>? header=null, IDictionary<string,object?>? data=null) |
API 网关 (app.Apis)
通过索引器或 Api() 取得 ApiMethodProxy:
var proxy = app.Apis["my-api"]; // 或 app.Apis.Api("my-api")
var res = await proxy.PostAsync(new Dictionary<string, object?> { ["k"] = "v" });
| 成员 | 签名 |
|---|---|
app.Apis[apiName] / Api(apiName) |
ApiMethodProxy |
proxy.GetAsync |
(string path="", Dictionary<string,string>? headers=null, string? token=null) |
proxy.PostAsync |
(Dictionary<string,object?>? body=null, string path="", Dictionary<string,string>? headers=null, string? token=null) |
proxy.PutAsync |
同 PostAsync |
proxy.DeleteAsync |
同 PostAsync |
proxy.PatchAsync |
同 PostAsync |
proxy.HeadAsync |
同 GetAsync |
proxy.OptionsAsync |
同 GetAsync |
proxy.RequestAsync |
(string method, Dictionary<string,object?>? body=null, string path="", Dictionary<string,string>? headers=null, string? token=null) |
app.Apis.CallApiAsync |
(CallApiOptions options) |
以上均返回 Task<ApiResponse>。
MySQL (app.MySql)
入口(推荐):
| 成员 | 签名 | 说明 |
|---|---|---|
From |
MySqlQueryBuilder From(string table) |
取查询构建器 |
Rdb |
MySqlRdb Rdb(string? instance=null, string? database=null) |
指定实例/数据库 |
MySqlQueryBuilder 链式方法(可直接 await,返回 MySqlResponse):
| 类别 | 方法 |
|---|---|
| 操作 | Select(string columns="*", MySqlSelectOptions?)、Insert(object values, MySqlInsertOptions?)、Update(object values, MySqlModifyOptions?)、Upsert(object values, MySqlUpsertOptions?)、Delete(MySqlModifyOptions?) |
| 过滤器 | Eq、Neq、Gt、Gte、Lt、Lte、Like、Is、In(col, IEnumerable)、Match(IDictionary)、Not(col, op, val)、Or(filters, referencedTable?)、Filter(col, op, val) |
| 修饰符 | Order(col, ascending=true, nullsFirst?, referencedTable?)、Limit(count, referencedTable?)、Range(from, to, referencedTable?)、Single()、MaybeSingle() |
| 执行 | ExecuteAsync() / await builder(GetAwaiter) |
扁平方法(兼容保留,app.MySql 上直接调用):
| 方法 | 签名 |
|---|---|
QueryAsync |
Task<MySqlResponse> (string table, string? schema=null, string? instance=null, MySqlQueryOptions? options=null) |
InsertAsync |
Task<MySqlWriteResponse> (string table, object data, string? schema=null, string? instance=null, bool upsert=false, string? onConflict=null) |
UpdateAsync |
Task<MySqlWriteResponse> (string table, Dictionary<string,object?> data, Dictionary<string,string> filters, string? schema=null, string? instance=null) |
DeleteAsync |
Task<MySqlWriteResponse> (string table, Dictionary<string,string> filters, string? schema=null, string? instance=null) |
CountAsync |
Task<MySqlCountResponse> (string table, Dictionary<string,string>? filters=null, string? schema=null, string? instance=null) |
文档数据库 (app.Database())
先 app.Database(string? instance=null, string? database=null) 取得 CloudBaseDb(默认实例/数据库 (default)),采用链式(Fluent)调用风格。
CloudBaseDb 入口:
| 成员 | 签名 | 返回 |
|---|---|---|
Collection |
CollectionReference Collection(string collectionName) |
CollectionReference |
Command |
DbCommand Command { get; } |
DbCommand |
RegExp |
Dictionary<string,object?> RegExp(string regexp, string? options=null) |
正则字典 |
CreateCollectionAsync |
(string collectionName) |
DbCollectionResult |
StartTransactionAsync |
() |
DbTransaction |
RunCommandsAsync |
(IEnumerable<object?> commands, string? transactionId=null) |
DbCommandResult |
CollectionReference / Query 链式方法:
| 方法 | 说明 |
|---|---|
Where(object) |
追加查询条件(可多次调用合并) |
OrderBy(string field, string direction="asc") |
排序 |
Limit(int) / Skip(int) |
分页(默认 limit 100) |
Field(object) |
字段投影 |
Get() / await |
执行查询,返回 DbQueryResult(Data / Total / Offset / Limit) |
Count() |
计数,返回 DbCountResult |
Add(object) |
新增(传数组则批量),返回 DbAddResult |
Update(object) |
按条件更新(multi),返回 DbUpdateResult;普通字段进 $set,操作符值按其键分组 |
Remove() |
按条件删除(multi),返回 DbDeleteResult |
Doc(string id) |
取单文档引用 DocumentReference |
Aggregate() |
取聚合构造器 DbAggregate |
DocumentReference 单文档方法(Collection(name).Doc(id)):
| 方法 | 说明 |
|---|---|
Get() / await |
读取单文档 |
Set(object) |
覆盖写入(upsert,整文档替换) |
Update(object) |
局部更新(multi=false,$set 分组) |
Remove() |
删除该文档 |
Field(object) |
字段投影 |
DbAggregate 聚合构造器(Collection(name).Aggregate(),End() 执行返回 DbAggregateResult):
Match / Group / Sort / Project / Limit / Skip / Lookup / Unwind / AddFields / Count / Sample / ReplaceRoot / SortByCount / Bucket / BucketAuto / GeoNear
DbTransaction 事务(await db.StartTransactionAsync()):Collection(name) 取事务内集合引用;CommitAsync() 提交;RollbackAsync() 回滚。
DbCommand 操作符(db.Command,一般命名为 _):
| 类别 | 操作符 |
|---|---|
| 查询 | Eq Neq Gt Gte Lt Lte In Nin And Or Not Nor Exists Mod All ElemMatch Size |
| 更新 | Set Remove Inc Mul Min Max Rename Bit Push Pop Shift Unshift Pull PullAll AddToSet |
响应均继承 DbResponse(IsSuccess / Code / Message / RequestId / StatusCode)。查询结果通过 result.Data 读取文档列表,result.Total 为总数。
数据模型 (app.Models)
模型操作句柄(app.Models["modelName"] 或 app.Models.Model("modelName")):
| 方法 | 签名 |
|---|---|
GetAsync |
(Dictionary<string,object?>? filter=null, Dictionary<string,object?>? select=null) |
GetByIdAsync |
(string recordId) |
ListAsync |
(filter?, select?, pageSize?, pageNumber?, getCount?, orderBy?) |
ListSimpleAsync |
(int? pageSize=null, int? pageNumber=null, bool? getCount=null) |
CreateAsync |
(Dictionary<string,object?> data) |
CreateManyAsync |
(List<Dictionary<string,object?>> data) |
UpdateAsync |
(Dictionary<string,object?> filter, Dictionary<string,object?> data) |
UpdateManyAsync |
(Dictionary<string,object?> filter, Dictionary<string,object?> data) |
UpsertAsync |
(filter, create?, update?) |
DeleteAsync |
(Dictionary<string,object?> filter) |
DeleteByIdAsync |
(string recordId) |
DeleteManyAsync |
(Dictionary<string,object?> filter) |
数据源相关(直接在 app.Models 上):
| 方法 | 说明 |
|---|---|
MysqlCommandAsync |
(string sqlTemplate, List<ModelMysqlParameter>? parameter=null, ModelMysqlConfig? config=null) |
GetAggregateDataSourceListAsync |
聚合数据源列表 |
GetDataSourceAggregateDetailAsync |
聚合数据源详情 |
GetDataSourceByTableNameAsync |
(List<string> tableNames) |
GetBasicDataSourceListAsync |
基础数据源列表 |
GetBasicDataSourceAsync |
基础数据源详情 |
GetSchemaListAsync |
(List<string>? dataSourceNameList=null) |
GetTableNameAsync |
(string? dataSourceName=null) |
云存储 (app.Storage)
先 app.Storage.From() 取得 CloudBaseStorageFileApi,再调用下列方法(均返回 Task<StorageResponse<T>>):
| 方法 | 签名 |
|---|---|
ThrowOnError |
CloudBaseStorageFileApi ThrowOnError()(链式,失败抛 StorageException) |
UploadAsync |
(string path, byte[] fileData, StorageUploadOptions? options=null) |
UpdateAsync |
(string path, byte[] fileData, StorageUploadOptions? options=null) |
DownloadAsync |
(string fileId, StorageTransformOptions? options=null) → byte[] |
GetUploadInfoAsync |
(List<string> paths) |
GetDownloadUrlsAsync |
(List<string> fileIds, int? expiresIn=null) |
CreateSignedUrlAsync |
(string fileId, int expiresIn, StorageSignedUrlOptions? options=null) |
CreateSignedUrlsAsync |
(List<string> fileIds, int expiresIn) |
CreateSignedUploadUrlAsync |
(string path) |
GetPublicUrlAsync |
(string pathOrFileId, StorageTransformOptions? options=null) |
InfoAsync |
(string pathOrFileId) → StorageFileInfo |
ExistsAsync |
(string pathOrFileId) → bool |
RemoveAsync |
(List<string> fileIds) |
CopyAsync |
(string fromPath, string toPath, bool overwrite=true) |
CopyBatchAsync |
(List<Dictionary<string,object?>> items) |
MoveAsync |
(string fromPath, string toPath, bool overwrite=true) |
错误处理
- 认证/数据模型/存储模块方法返回封装对象,通过
IsSuccess/Error判断。 - HTTP 层网络错误会抛出
AuthError(包含Code、ErrorMessage、Status)。
try
{
var r = await app.CallFunctionAsync("hello");
}
catch (AuthError e)
{
Console.WriteLine($"[{e.Code}] {e.ErrorMessage}");
}
自定义键值存储
默认使用 FileKeyValueStore(持久化到 ~/.cloudbase 或 %APPDATA%/cloudbase)。
可自行实现 IKeyValueStore 或使用内置的 InMemoryKeyValueStore:
var app = await CloudBaseApp.InitAsync(
env: "your-env-id",
store: new InMemoryKeyValueStore());
目录结构
src/CloudBase/ SDK 源码
├── CloudBase.cs 主入口类
├── CloudBaseConfig.cs 配置
├── Auth/ 认证模块
├── Captcha/ 验证码模块
├── Http/ HTTP 客户端
├── Internal/ JSON 等内部工具
├── Models/ 数据模型(请求/响应)
├── Modules/ 云函数、云托管、API、MySQL、数据模型、存储
└── Storage/ 键值存储抽象
unity/
└── com.tencent.cloudbase/ Unity UPM 包(预编译多平台 DLL + 适配层源码,Git URL 安装)
examples/
├── QuickStart/ 快速上手示例
├── TerminalUI/ 交互式终端测试工具(基于 Spectre.Console)
└── UnityGame/ Unity 完整示例(含适配层源码 CloudBaseGame/)
scripts/
├── publish.sh 发布脚本(nuget / unity / unity-package)
└── publish.ps1 发布脚本(Windows PowerShell)
artifacts/ NuGet 打包产物(*.nupkg)
CloudBase.sln 解决方案
发布
发布(NuGet 包与 Unity UPM 包两条分发线的构建、打包、推送与打 tag)属于维护者操作,完整流程见 CONTRIBUTION.md 的「发布」章节。
许可证
本项目基于 MIT 许可证 开源。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.