TORM.SqlServer
2.0.16
dotnet add package TORM.SqlServer --version 2.0.16
NuGet\Install-Package TORM.SqlServer -Version 2.0.16
<PackageReference Include="TORM.SqlServer" Version="2.0.16" />
<PackageVersion Include="TORM.SqlServer" Version="2.0.16" />
<PackageReference Include="TORM.SqlServer" />
paket add TORM.SqlServer --version 2.0.16
#r "nuget: TORM.SqlServer, 2.0.16"
#:package TORM.SqlServer@2.0.16
#addin nuget:?package=TORM.SqlServer&version=2.0.16
#tool nuget:?package=TORM.SqlServer&version=2.0.16
<p align="center"> <img src="logo.svg" width = "400" height = "200" alt="TORM Logo"/> </p>
<h1 align="center">TORM - 高性能 .NET ORM 框架</h1>
<div align="center">
轻量级、高性能、功能丰富的对象关系映射框架
ThingsGateway 生态系统中的 ORM 组件,专为高性能场景设计。
</div>
中文
📖 项目简介
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是一个没有任何历史包袱的项目,其高性能设计和批量操作优化,在大数据量场景下表现尤为突出。
注:实际性能因数据库类型、数据量、硬件配置等因素会有所不同。建议在实际项目环境中进行测试。
运行性能测试
cd benchmark/TORM.Benchmark
dotnet run -c Release
🚀 快速开始
安装 NuGet 包
dotnet add package TORM
基础配置
using TORM;
// 创建 ORM 客户端
using var ormClient = new OrmClient(new OrmConnectionConfig
{
DatabaseType = OrmDbType.MySql,
ConnectionString = "Server=localhost;Database=test;Uid=root;Pwd=password;"
});
定义实体
[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 自动建表
// 自动创建表结构
await ormClient.CodeFirst.InitTableAsync<User>();
📚 功能详解
查询操作
// 基础查询
var list = await ormClient.Queryable<User>().ToListAsync();
// 条件查询
var adults = await ormClient.Queryable<User>()
.Where(u => u.Age >= 18)
.ToListAsync();
// 分页查询(返回 PagedList<T>,包含总数)
var page = await ormClient.Queryable<User>()
.Where(u => u.IsActive)
.OrderByDescending(u => u.CreateTime)
.ToPageListAsync(pageNumber: 1, pageSize: 20);
// 聚合查询
var count = await ormClient.Queryable<User>().CountAsync();
var exists = await ormClient.Queryable<User>().AnyAsync();
// 投影查询
var names = await ormClient.Queryable<User>()
.Select(u => new { u.Id, u.Name })
.ToListAsync();
// 流式查询(大数据量场景)
await foreach (var user in ormClient.Queryable<User>().ToAsyncEnumerable())
{
// 逐行处理
}
批量操作
// 批量插入(高性能)
await ormClient.InsertableRange(users).ExecuteAsync();
// BulkCopy 批量导入(最高性能)
await ormClient.BulkCopy<User>().BulkInsertAsync(users);
// 批量更新
await ormClient.BulkCopy<User>().BulkUpdateAsync(users);
// 批量保存(自动判断插入/更新)
await ormClient.BulkCopy<User>().BulkMergeAsync(users);
分表操作
定义分表实体:
// 按月分表:表名后缀格式 _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; }
}
分表操作示例:
// 分表查询(自动跨所有分表查询,可指定时间范围)
var list = await ormClient.SplitQueryableAsync<Log>(
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 |
事务管理
await db.UseTranAsync(async () =>
{
await db.InsertableRange(addModels).ExecuteAsync().ConfigureAwait(false);
}).ConfigureAwait(false);
AOP 日志拦截
// 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 协议开源。
| Product | Versions 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 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. |
-
net10.0
- Microsoft.Data.SqlClient (>= 7.0.1)
- TORM (>= 2.0.16)
-
net8.0
- Microsoft.Data.SqlClient (>= 7.0.1)
- System.Formats.Asn1 (>= 10.0.7)
- TORM (>= 2.0.16)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on TORM.SqlServer:
| Package | Downloads |
|---|---|
|
ThingsGatewayRuntime.Plugin
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.