# TORM
**Repository Path**: ThingsGateway/TORM
## Basic Information
- **Project Name**: TORM
- **Description**: TORM 是一个为 .NET 平台设计的轻量级、高性能 ORM(对象关系映射)框架。它提供了简洁流畅的 API,支持多种数据库,并针对高性能场景进行了深度优化。
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 6
- **Forks**: 2
- **Created**: 2026-04-05
- **Last Updated**: 2026-04-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
TORM - 高性能 .NET ORM 框架
[](https://www.apache.org/licenses/LICENSE-2.0.html)
[](https://www.nuget.org/packages/TORM)
[](https://dotnet.microsoft.com/)
**轻量级、高性能、功能丰富的对象关系映射框架**
**ThinsGateway** 生态系统中的 **ORM** 组件,专为高性能场景设计。
---
## 中文
### 📖 项目简介
TORM 是一个为 .NET 平台设计的轻量级、高性能 ORM(对象关系映射)框架。它提供了简洁流畅的 API,支持多种数据库,并针对高性能场景进行了深度优化。
### ✨ 核心特性
#### 🚀 高性能设计
- **AOT**:支持AOT编译
- **表达式树解析**:高效的 LINQ 表达式到 SQL 转换
- **批量操作优化**:支持 BulkCopy 高性能批量插入/更新
#### 🗄️ 多数据库支持
| 数据库 | 支持状态 |
|--------|----------|
| MySQL | ✅ 完全支持 |
| SQL Server | ✅ 完全支持 |
| PostgreSQL | ✅ 完全支持 |
| SQLite | ✅ 完全支持 |
| TDengine | 暂无映射功能,修改自官方驱动库(原生 + WebSocket),完善AOT支持,可自定义ADO.NET操作 |
#### 💡 丰富的功能
**基础 CRUD 操作**
**高级功能**
- 🔹 **Code First**:自动创建/更新数据库表结构
- 🔹 **分表分库**:支持时间分表、数量分表策略
- 🔹 **批量操作**:BulkCopy 高性能批量导入
- 🔹 **事务管理**:支持同步/异步事务
- 🔹 **AOP 拦截**:SQL 执行前后拦截,日志记录
- 🔹 **JSON 支持**:原生 JSON 类型支持
### 📊 性能测试
TORM 与国内主流 ORM 框架 的Sqlite性能对比测试结果:
```
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8037/25H2/2025Update/HudsonValley2)
Intel Core Ultra 9 285H 2.90GHz, 1 CPU, 16 logical and 16 physical cores
.NET SDK 10.0.103
[Host] : .NET 10.0.3 (10.0.3, 10.0.326.7603), X64 RyuJIT x86-64-v3
.NET 10.0 : .NET 10.0.3 (10.0.3, 10.0.326.7603), X64 RyuJIT x86-64-v3
Job=.NET 10.0 Runtime=.NET 10.0
```
| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
|--------------------------- |-----------------:|----------------:|----------------:|-----------------:|------:|--------:|------------:|-----------:|----------:|-------------:|------------:|
| TORM_BulkInsert_10000 | 29,483.870 μs | 564.6185 μs | 554.5309 μs | 29,662.345 μs | 1.00 | 0.03 | 1062.5000 | - | - | 13392.2 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_BulkInsert_10000 | 54,989.997 μs | 1,048.1157 μs | 1,076.3376 μs | 55,272.167 μs | 1.00 | 0.03 | 2833.3333 | 1000.0000 | 166.6667 | 34263.76 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_BulkInsert_10000 | 537,387.137 μs | 14,137.7720 μs | 41,240.5475 μs | 553,427.500 μs | 1.01 | 0.12 | 5000.0000 | 1000.0000 | - | 64690.97 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_BulkInsert_50000 | 156,769.159 μs | 1,091.2339 μs | 967.3505 μs | 156,778.888 μs | 1.00 | 0.01 | 5250.0000 | - | - | 66934.26 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_BulkInsert_50000 | 268,856.227 μs | 3,064.4750 μs | 2,866.5118 μs | 269,124.600 μs | 1.00 | 0.01 | 14000.0000 | 4000.0000 | 1000.0000 | 168710.47 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_BulkInsert_50000 | 2,791,199.208 μs | 55,809.9648 μs | 97,746.6592 μs | 2,802,945.200 μs | 1.00 | 0.05 | 26000.0000 | 1000.0000 | - | 323409.88 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_BulkUpdate_50000 | 99,459.911 μs | 967.6688 μs | 905.1580 μs | 99,733.850 μs | 1.00 | 0.01 | 5333.3333 | - | - | 66933.79 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_BulkUpdate_50000 | 182,485.632 μs | 2,967.7149 μs | 2,630.8020 μs | 182,848.775 μs | 1.00 | 0.02 | 14500.0000 | 4000.0000 | 1500.0000 | 168710.39 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_BulkUpdate_50000 | 2,588,248.118 μs | 51,038.1952 μs | 52,412.4689 μs | 2,598,517.600 μs | 1.00 | 0.03 | 42000.0000 | 1000.0000 | - | 521759.37 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_DeleteBatch_10000 | 7.996 μs | 0.0541 μs | 0.0480 μs | 8.006 μs | 1.00 | 0.01 | 0.1831 | - | - | 2.4 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_DeleteBatch_10000 | 69.195 μs | 1.0972 μs | 1.0263 μs | 69.525 μs | 1.00 | 0.02 | 0.9155 | - | - | 11.49 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_DeleteBatch_10000 | 65.489 μs | 0.5363 μs | 0.4754 μs | 65.528 μs | 1.00 | 0.01 | 0.5493 | - | - | 7.01 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_GetList | 9.035 μs | 0.0527 μs | 0.0493 μs | 9.045 μs | 1.00 | 0.01 | 0.5035 | - | - | 6.2 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_GetList | 90.299 μs | 1.7914 μs | 3.6995 μs | 90.835 μs | 1.00 | 0.07 | 2.0752 | 0.9766 | - | 25.61 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_GetList | 66.647 μs | 1.3142 μs | 2.2316 μs | 67.329 μs | 1.00 | 0.05 | 0.8545 | 0.7935 | - | 10.76 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_InsertBatch_10000 | 29,821.968 μs | 117.4661 μs | 104.1306 μs | 29,839.409 μs | 1.00 | 0.00 | 1062.5000 | - | - | 13391.97 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_InsertBatch_10000 | 119,720.489 μs | 1,983.6632 μs | 1,758.4657 μs | 119,777.158 μs | 1.00 | 0.02 | 6500.0000 | 3166.6667 | 1000.0000 | 72158.74 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_InsertBatch_10000 | 562,874.180 μs | 3,067.5205 μs | 2,869.3606 μs | 562,098.900 μs | 1.00 | 0.01 | 5000.0000 | 1000.0000 | - | 64691.03 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_InsertBatch_50000 | 156,858.300 μs | 1,981.4147 μs | 1,756.4725 μs | 156,255.650 μs | 1.00 | 0.02 | 5000.0000 | - | - | 66934.18 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_InsertBatch_50000 | 587,029.233 μs | 8,298.3128 μs | 6,478.7768 μs | 587,832.350 μs | 1.00 | 0.02 | 28000.0000 | 13000.0000 | 2000.0000 | 343406.52 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_InsertBatch_50000 | 2,743,381.907 μs | 22,418.0622 μs | 19,873.0282 μs | 2,748,549.050 μs | 1.00 | 0.01 | 26000.0000 | 1000.0000 | - | 323409.86 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_SaveBatchUpsert_1000 | 2,488.677 μs | 13.5737 μs | 11.3346 μs | 2,487.567 μs | 1.00 | 0.01 | 109.3750 | - | - | 1361.35 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_SaveBatch_1000 | 3,214.556 μs | 52.0409 μs | 48.6791 μs | 3,198.125 μs | 1.00 | 0.02 | 156.2500 | 15.6250 | - | 2098.54 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_SaveBatch_1000 | 116,875.679 μs | 2,299.9455 μs | 2,361.8747 μs | 116,837.275 μs | 1.00 | 0.03 | 7500.0000 | 1000.0000 | - | 96188.28 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_SaveBatch_1000 | 6,921.216 μs | 136.1796 μs | 127.3824 μs | 6,879.202 μs | 1.00 | 0.03 | 234.3750 | 117.1875 | 70.3125 | 2566.44 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_SaveBulk_50000 | 130,866.535 μs | 2,607.0517 μs | 7,003.6756 μs | 132,598.750 μs | 1.00 | 0.08 | 5500.0000 | - | - | 67716.66 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_SaveBulk_50000 | 6,335,388.058 μs | 124,308.3524 μs | 170,154.6902 μs | 6,390,547.400 μs | 1.00 | 0.04 | 712000.0000 | 60000.0000 | 9000.0000 | 8634677.2 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_SaveBulk_50000 | 199,689.818 μs | 3,965.4261 μs | 11,184.5554 μs | 202,523.525 μs | 1.00 | 0.08 | 8500.0000 | 2000.0000 | 500.0000 | 129874.98 KB | 1.00 |
| | | | | | | | | | | | |
| TORM_UpdateBatch_1000 | 2,059.663 μs | 13.8345 μs | 12.9408 μs | 2,055.851 μs | 1.00 | 0.01 | 109.3750 | - | - | 1344.37 KB | 1.00 |
| | | | | | | | | | | | |
| SqlSugar_UpdateBatch_1000 | 53,523.906 μs | 1,172.7374 μs | 3,364.8036 μs | 54,097.327 μs | 1.01 | 0.11 | 909.0909 | 727.2727 | 181.8182 | 11012.93 KB | 1.00 |
| | | | | | | | | | | | |
| FreeSql_UpdateBatch_1000 | 53,324.506 μs | 650.2690 μs | 608.2620 μs | 53,067.340 μs | 1.00 | 0.02 | 800.0000 | 200.0000 | - | 10461.04 KB | 1.00 |
可以看出,TORM无论是速度还是内存占用都表现优异,得益于TORM是一个没有任何历史包袱的项目,其高性能设计和批量操作优化,在大数据量场景下表现尤为突出。
> 注:实际性能因数据库类型、数据量、硬件配置等因素会有所不同。建议在实际项目环境中进行测试。
#### 运行性能测试
```bash
cd benchmark/TORM.Benchmark
dotnet run -c Release
```
### 🚀 快速开始
#### 安装 NuGet 包
```bash
dotnet add package TORM
```
#### 基础配置
```csharp
using TORM;
// 创建 ORM 客户端
var ormClient = new OrmClient(new OrmConnectionConfig
{
DatabaseType = OrmDbType.MySql,
ConnectionString = "Server=localhost;Database=test;Uid=root;Pwd=password;"
});
```
#### 定义实体
```csharp
[OrmTable(TableName = "users")]
public class User
{
[OrmColumn(IsPrimaryKey = true, IsIdentity = true)]
public long Id { get; set; }
[OrmColumn(ColumnName = "user_name", Length = 50)]
public string Name { get; set; }
public int Age { get; set; }
public DateTime CreateTime { get; set; }
}
```
#### Code First 自动建表
```csharp
// 自动创建表结构
await ormClient.CodeFirst.InitTableAsync();
```
### 📚 功能详解
#### 查询操作
```csharp
// 基础查询
var list = await ormClient.Queryable().ToListAsync();
// 条件查询
var adults = await ormClient.Queryable()
.Where(u => u.Age >= 18)
.ToListAsync();
// 分页查询(返回 PagedList,包含总数)
var page = await ormClient.Queryable()
.Where(u => u.IsActive)
.OrderByDescending(u => u.CreateTime)
.ToPageListAsync(pageNumber: 1, pageSize: 20);
// 聚合查询
var count = await ormClient.Queryable().CountAsync();
var exists = await ormClient.Queryable().AnyAsync();
// 投影查询
var names = await ormClient.Queryable()
.Select(u => new { u.Id, u.Name })
.ToListAsync();
// 流式查询(大数据量场景)
await foreach (var user in ormClient.Queryable().ToAsyncEnumerable())
{
// 逐行处理
}
```
#### 批量操作
```csharp
// 批量插入(高性能)
await ormClient.InsertableRange(users).ExecuteAsync();
// BulkCopy 批量导入(最高性能)
await ormClient.BulkCopy().BulkInsertAsync(users);
// 批量更新
await ormClient.BulkCopy().BulkUpdateAsync(users);
// 批量保存(自动判断插入/更新)
await ormClient.BulkCopy().BulkMergeAsync(users);
```
#### 分表操作
**定义分表实体:**
```csharp
// 按月分表:表名后缀格式 _yyyyMM
[OrmTable(TableName = "logs", SplitType = SplitTableType.Month, SplitColumn = nameof(CreateTime))]
public class Log
{
[OrmColumn(IsPrimaryKey = true, IsIdentity = true)]
public long Id { get; set; }
public string Message { get; set; }
// 分表依据列(必须为 DateTime 类型)
public DateTime CreateTime { get; set; }
}
// 按记录数分表:每 10000 条自动创建新表
[OrmTable(TableName = "sensor_data", MaxRowCount = 10000)]
public class SensorData
{
[OrmColumn(IsPrimaryKey = true, IsIdentity = true)]
public long Id { get; set; }
public double Value { get; set; }
}
// 混合策略:按月分表 + 每月内按记录数分表
[OrmTable(TableName = "events",
SplitType = SplitTableType.Month,
SplitColumn = nameof(EventTime),
MaxRowCount = 50000)]
public class Event
{
[OrmColumn(IsPrimaryKey = true, IsIdentity = true)]
public long Id { get; set; }
public DateTime EventTime { get; set; }
}
```
**分表操作示例:**
```csharp
// 分表查询(自动跨所有分表查询,可指定时间范围)
var list = await ormClient.SplitQueryableAsync(
query => query.Where(l => l.Message.Contains("error")),
startTime: DateTime.Now.AddDays(-30),
endTime: DateTime.Now
);
// 分表插入(自动路由到正确的分表)
await ormClient.SplitInsertableAsync(logs);
// 分表更新
await ormClient.SplitUpdateableAsync(logs, update => update.Set(l => l.Message, "updated"));
// 分表删除
await ormClient.SplitDeleteableAsync(logs);
```
**分表类型说明:**
| SplitTableType | 说明 | 表名后缀格式 |
|----------------|------|-------------|
| None | 不分表(默认) | - |
| Week | 按周分表 | _yyyyMMdd(周一日期) |
| Month | 按月分表 | _yyyyMM |
| Quarter | 按季度分表 | _yyyyQn |
| Year | 按年分表 | _yyyy |
#### 事务管理
```csharp
await db.UseTranAsync(async () =>
{
await db.InsertableRange(addModels).ExecuteAsync().ConfigureAwait(false);
}).ConfigureAwait(false);
```
#### AOP 日志拦截
```csharp
// SQL执行前日志
ormClient.Aop.OnLogExecuting = (sql, parameters) =>
{
Console.WriteLine($"执行SQL: {sql}");
};
// SQL执行后日志
ormClient.Aop.OnLogExecuted = (sql, parameters, elapsed) =>
{
Console.WriteLine($"SQL执行耗时: {elapsed.TotalMilliseconds}ms");
};
// 插入/更新前修改值
ormClient.Aop.OnDataExecuting = (args) =>
{
if (args.DataExecutingType == DataExecutingType.Insert)
{
// 自动填充创建时间
if (args.Entity is BaseEntity entity)
{
entity.CreateTime = DateTime.Now;
}
}
};
```
### 🏗️ 项目结构
```
TORM/
├── src/TORM/ # 核心库
│ ├── Ado/ # ADO.NET 基础设施
│ ├── Aop/ # AOP 拦截器
│ ├── Attributes/ # 实体特性
│ ├── BulkCopy/ # 批量操作
│ ├── Client/ # ORM 客户端
│ ├── CodeFirst/ # Code First
│ ├── Queryable/ # 查询提供器
│ ├── Insertable/ # 插入提供器
│ ├── Updateable/ # 更新提供器
│ ├── Deletable/ # 删除提供器
│ ├── Saveable/ # 保存提供器
│ ├── SplitTable/ # 分表支持
│ ├── Sql/ # SQL 构建
│ └── TaosData/ # TDengine 支持
│ ├── Driver/ # TDengine 驱动
│ └── TMQ/ # TMQ 消息队列
├── benchmark/TORM.Benchmark/ # 性能测试
└── test/TORM.Test/ # 单元测试
```
### 📄 开源协议
本项目基于 [Apache 2.0](LICENSE) 协议开源。