DataTables.API 1.0.10

dotnet add package DataTables.API --version 1.0.10
                    
NuGet\Install-Package DataTables.API -Version 1.0.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DataTables.API" Version="1.0.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DataTables.API" Version="1.0.10" />
                    
Directory.Packages.props
<PackageReference Include="DataTables.API" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DataTables.API --version 1.0.10
                    
#r "nuget: DataTables.API, 1.0.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DataTables.API@1.0.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DataTables.API&version=1.0.10
                    
Install as a Cake Addin
#tool nuget:?package=DataTables.API&version=1.0.10
                    
Install as a Cake Tool

Table of Contents

DataTables

GitHub Actions Releases

DataTables 把 Excel .xlsx/.xlsm.csv 配置生成强类型 C# 代码和配套 .bytes 数据,运行时面向 .NET 服务端与 Unity 客户端。项目提供异步数据源读取、并发单飞加载、独立 DataTableContext、可选的 LRU 表缓存,以及可组合的数据源装饰器。

生成代码和 .bytes 是同一份 schema 的两个组成部分,必须一起生成、一起发布。

文档

快速开始

.NET Core 项目

  1. 安装运行时和生成器:
dotnet add package DataTables.API
dotnet tool install --global DataTables.Generator
  1. 创建 Tables/Scene.xlsx(也可使用 .xlsm 或单工作表 .csv)。以下示例假定工作表的 Class=Scene,因此会生成表类 DTScene 和默认行前缀对应的行类:
A 列 B 列
1 DTGen=Table, Title=Scene, Class=Scene, Index=Id
2 场景 ID 场景名称
3 Id Name
4 int string
5 1 Town
  1. 生成 C# 与数据文件:
dotnet dtgen -i ./Tables -patterns "*.xlsx" -patterns "*.xlsm" -patterns "*.csv" -co ./Generated -do ./Data -p DR

SDK 风格项目会自动编译 Generated/**/*.cs。若运行目录不是项目目录,把数据复制到输出目录:

<ItemGroup>
  <None Update="Data/*.bytes" CopyToOutputDirectory="PreserveNewest" />
  <None Update="Data/manifest.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
  1. 配置数据目录并加载:
using System;
using System.IO;
using System.Threading.Tasks;
using DataTables;

public static class Program
{
    public static async Task Main()
    {
        using var context = new DataTableContext(
            new FileSystemDataSource(Path.Combine(AppContext.BaseDirectory, "Data")));
        context.EnableEstimatedMemoryBudget(50);

        var scenes = await context.LoadAsync<DTScene>();
        if (scenes is null)
        {
            throw new InvalidOperationException("DTScene was not loaded.");
        }

        Console.WriteLine($"Loaded {scenes.Count} scenes.");
        Console.WriteLine($"Loaded state: {context.IsLoaded<DTScene>()}");

        var cachedScenes = context.GetCached<DTScene>();
        var town = DTScene.GetById(context, 1);
        Console.WriteLine($"Same cached instance: {ReferenceEquals(scenes, cachedScenes)}");
        Console.WriteLine($"Scene: {town?.Name}");
    }
}

EnableEstimatedMemoryBudget(50) 表示“缓存项估算值合计不超过 50 MiB”,不是进程实际托管内存的硬上限。需要更准确的项目级估算时,传入 Func<DataTableBase, long> 大小估算器。 若单张表的估算值已超过整个预算,当前 LoadAsync 调用仍会得到该表,但它不会进入缓存;随后 GetCached 返回 nullIsLoaded 返回 false,再次加载会重新读取。生产配置应给单表峰值留出空间。

Unity项目

Releases 获取 Unity 包,并使用独立 CLI 生成 C#、.bytesmanifest.json。放入 StreamingAssets 时三者必须一起部署;Android 与 WebGL 由正式的 StreamingAssetsDataSource 使用 UnityWebRequest 异步读取,其他平台使用异步文件流。

Unity 生命周期入口可以使用 async void,但必须在入口内捕获异常:

using System;
using System.Threading;
using DataTables;
using UnityEngine;

public sealed class DataBootstrap : MonoBehaviour
{
    private readonly CancellationTokenSource _lifetime = new();

    private async void Start()
    {
        try
        {
            using var context = new DataTableContext(
                new StreamingAssetsDataSource(Application.streamingAssetsPath));
            context.EnableEstimatedMemoryBudget(30);

            var scenes = await context.LoadAsync<DTScene>(cancellationToken: _lifetime.Token);
            var town = DTScene.GetById(context, 1);
            Debug.Log($"Loaded {scenes?.Count ?? 0} scenes; town={town?.Name}.");
        }
        catch (OperationCanceledException) when (_lifetime.IsCancellationRequested) { }
        catch (Exception exception)
        {
            Debug.LogException(exception);
        }
    }

    private void OnDestroy() => _lifetime.Cancel();
}

Unity 构建中也可使用 new StreamingAssetsDataSource(),它等价于传入 Application.streamingAssetsPath

src/DataTables 是运行时源码的修改源;Unity 镜像位于 src/DataTables.Unity/Assets/Scripts/DataTables/Runtime,由构建同步,不应直接编辑。

推荐运行时 API

新代码围绕三组查询 API 编写:

目的 API 行为
加载 await LoadAsync<T>(name, cancellationToken) 未加载时读取并解析;同一表的并发请求共享一次加载。
读取缓存 GetCached<T>(name) 只读取已加载实例,不触发 I/O。
检查状态 IsLoaded<T>(name) 检查指定类型与名称的表是否已发布。

它们同时存在于默认静态门面 DataTableManager 和独立的 DataTableContextname 默认为空字符串;拆分表或同类型多实例必须在三处使用相同名称:

var shard = await DataTableManager.LoadAsync<DTScene>("x001", cancellationToken);
var cachedShard = DataTableManager.GetCached<DTScene>("x001");
var shardIsLoaded = DataTableManager.IsLoaded<DTScene>("x001");

生成的强类型静态查询全部是 context-first,不会隐式访问默认全局 Manager:

using var context = new DataTableContext(new FileSystemDataSource("./Data"));
var scene = DTScene.GetById(context, 1001);
var shardScene = DTScene.GetById(context, "x001", 1001);

table / matrix / kv / graph / tree 都遵循同一规则;实例查询 API 仍保留。升级生成器后必须重新生成 C#,旧的无 context 查询、静态查询属性和 *Static 别名不再生成。

旧的回调加载、CreateDataTable*GetDataTable*HasDataTable*EnableMemoryManagement 等兼容别名已在破坏性清理中移除;代码应直接使用 LoadAsync / GetCached / IsLoaded / EnableEstimatedMemoryBudget

独立上下文

多租户、测试隔离或同进程加载多套配置时使用独立上下文:

using var context = new DataTableContext(new FileSystemDataSource("./TenantA/Data"));
context.EnableEstimatedMemoryBudget(50);

var scenes = await context.LoadAsync<DTScene>();
var cachedScenes = context.GetCached<DTScene>();
var isLoaded = context.IsLoaded<DTScene>();

每个上下文独立持有数据源、加载任务、缓存、取消生命周期、统计和 Hook。单次 LoadAsync 的调用方 token 只取消该调用方的等待,不会中断其他调用方共享的加载;切换数据源、ClearCache 或释放上下文才会取消该上下文仍在进行的底层读取。

生成的注册清单可直接做有界预热。默认并发度为 4;fail-fast 只停止领取新表,已经启动的加载仍会完成并写入逐表结果:

using var context = new DataTableContext(new FileSystemDataSource("./Data"));
DataTableManagerExtension.Register(context);
var preheat = await context.PreheatAsync(
    Priority.Critical | Priority.Normal,
    new PreheatOptions(maxConcurrency: 4, failFast: true),
    cancellationToken);

foreach (var table in preheat.Tables)
{
    Console.WriteLine($"{table.TableType.Name}/{table.Name}: {table.Status}");
}

PreheatResult 包含汇总 Stats、稳定排序的逐表状态和 StopReason。状态为 CacheHitLoadedFailedCanceledNotStarted;运行中调用方取消返回部分结果,调用前已经取消仍直接抛出 OperationCanceledException

I/O 与解析线程

payload I/O 始终异步读取并完整缓冲。同步二进制解析默认使用 DataTableParseExecution.BackgroundThread;不支持后台线程的 Unity WebGL Player 会自动在调用上下文解析。CallingContext 表示在 I/O 后的 async continuation 上解析:Unity 捕获主线程同步上下文时会回到主线程,没有同步上下文时不承诺固定线程。若需要显式采用该策略,可设置:

DataTableManager.ParseExecution = DataTableParseExecution.CallingContext;

大表在调用上下文解析可能产生可见卡顿,应在目标平台实测启动和热更新流程。 使用后台解析时,行的 Deserialize 和自定义类型转换必须是纯数据、线程安全代码,不能访问 Unity 对象;确实依赖 Unity 主线程的自定义解析应选择 CallingContext

代码生成器

查看真实命令契约:

dotnet dtgen --help
dotnet dtgen data --help
dotnet dtgen validate --help

完整生成示例:

dotnet dtgen \
  -i ./Tables \
  -patterns "*.xlsx" -patterns "*.xlsm" -patterns "*.csv" \
  -co ./Generated \
  -do ./Data \
  -n MyGame \
  -p DR \
  -t "CLIENT && !SERVER" \
  -f

解析与诊断示例:

dotnet dtgen \
  -i ./Tables \
  -patterns "*.xlsx" -patterns "*.xlsm" -patterns "*.csv" \
  -co ./Generated \
  -do ./Data \
  --formula-policy ValidateOnly \
  --column-comment-marker-text "#列注释标志" \
  --row-comment-marker-text "#行注释标志" \
  --skip-cell-marker "#" \
  --array-nested-separators "|#-" \
  --diagnostics-json-output ./artifacts/diagnostics.json

--strict-name-validation--validate-formula-consistency 默认已启用;通常无需传入。它们是 bool 开关,命令中不要在开关后追加 true

只重新生成数据文件时使用 data 子命令:

dotnet dtgen data -i ./Tables -patterns "*.xlsx" -patterns "*.xlsm" -patterns "*.csv" -do ./Data -p DR

CI 或预提交只校验 Excel/schema、诊断与代码模板可渲染性,不写入 C#、.bytes 或 manifest 时,使用 validate 子命令:

dotnet dtgen validate \
  -i ./Tables \
  -patterns "*.xlsx" -patterns "*.xlsm" -patterns "*.csv" \
  -n MyGame \
  -p DR \
  --diagnostics-json-output ./artifacts/diagnostics.json

所有长参数使用 kebab-case。CLI 文档示例由测试与实际 --help 输出保持一致。

表格式与生成物

Excel/CSV 表的前四行依次是 sheet 元信息、列描述、C# 字段名和字段类型,数据从第五行开始。当前支持 tablematrixcolumnkvtreegraph;具体布局、索引声明、标签过滤与类型语法见表类型指南。A1 可用 tags=S&C 声明工作表/子逻辑表标签,-t 是布尔表达式(例如 C && !S);未声明标签的表始终包含,disabletagsfilter 会同时关闭表级和字段级过滤。

生成结果包含:

  • 表类与行类 C# 文件;
  • DataTableManagerExtension.cs 注册清单;
  • 带版本、表标识与 schema hash 的 .bytes 文件;
  • 运行时使用的 manifest.json(CodeAndData/DataOnly 模式);
  • 仅供生成器使用的增量 manifest v2,其输入和输出均为稳定相对标识。

部署时把 manifest.json 与同目录 .bytes 一起复制。validate 模式不会写任何产物;生成失败或事务提交冲突会保留上一版数据与 manifest。

运行时会校验二进制版本、表标识、schema hash、flags 和尾随字节。出现版本或 schema 不匹配时,应从同一输入重新生成代码和数据,不要单独替换其中一项。协议细节见二进制格式 v3

数据源与缓存边界

UseFileSystem 适合本地文件,并优先读取同目录 manifest.json,缺失时才回退到目录枚举。NetworkDataSource 每次请求配置的 manifest URI,不永久缓存,也不会自动校验下载流;网络、Unity StreamingAssets、版本目录、压缩、加密、hash、原始字节缓存和 fallback 的正确组合顺序见数据源管线。需要特别区分两种预算:

  • EnableEstimatedMemoryBudget 管理已解析数据表的 LRU 估算预算;
  • CachedDataSource 管理完整 payload byte[] 的独立、按字节计数的有界 LRU 缓存。

二者不是同一份缓存,也都不代表进程总内存上限。

升级与兼容

本次 context-first 查询与 PreheatResult 是源码级破坏性变更,升级后必须重新生成并重新编译生成代码;运行时 DataTableManager facade 和生成的无参 Register() 仍保留。二进制协议仍是 v3,数据格式没有改变,但部署需要新增 manifest.json。完整步骤和错误说明见 v3 迁移指南

开发与验证

dotnet build DataTables.sln
dotnet test tests/DataTables.Tests/DataTables.Tests.csproj

修改 src/DataTables 后,构建会同步 Unity 运行时镜像。提交前还应运行仓库内的 Unity 同步校验脚本并确认镜像没有漂移。

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.10 38 7/17/2026
1.0.9 46 7/16/2026
1.0.8 50 7/14/2026
1.0.6 95 7/12/2026
1.0.2 105 7/11/2026
1.0.1 95 7/9/2026
1.0.0 104 7/7/2026
0.14.2 147 5/18/2026
0.13.26 111 5/18/2026
0.13.24 107 5/17/2026
0.13.22 120 5/17/2026
0.13.19 387 9/9/2025
0.13.18 261 9/8/2025
0.13.16 260 9/8/2025
0.13.15 230 8/24/2025
0.13.14 259 8/21/2025
0.13.13 275 8/20/2025
0.13.12 256 8/20/2025
0.13.10 273 8/13/2025
0.13.9 274 8/13/2025
Loading failed