Sqlx 0.6.5

There is a newer version of this package available.
See the version list below for details.
dotnet add package Sqlx --version 0.6.5
                    
NuGet\Install-Package Sqlx -Version 0.6.5
                    
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="Sqlx" Version="0.6.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sqlx" Version="0.6.5" />
                    
Directory.Packages.props
<PackageReference Include="Sqlx" />
                    
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 Sqlx --version 0.6.5
                    
#r "nuget: Sqlx, 0.6.5"
                    
#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 Sqlx@0.6.5
                    
#: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=Sqlx&version=0.6.5
                    
Install as a Cake Addin
#tool nuget:?package=Sqlx&version=0.6.5
                    
Install as a Cake Tool

Sqlx

NuGet License .NET LTS Tests AOT

高性能、AOT 友好的 .NET 数据库访问库。使用源生成器在编译时生成代码,零运行时反射,完全支持 Native AOT。

核心特性

  • 🚀 高性能 - 比 Dapper.AOT 快 1.5-2.9%,最低 GC 压力(Gen1 GC 是 FreeSql 的 1/13)
  • ⚡ 零反射 - 编译时源生成,运行时无反射开销
  • 🎯 类型安全 - 编译时验证 SQL 模板和表达式
  • 🌐 多数据库 - SQLite、PostgreSQL、MySQL、SQL Server、Oracle、DB2
  • 📦 AOT 就绪 - 完全支持 Native AOT,通过 1564 个单元测试
  • 🔧 LINQ 支持 - IQueryable 接口,支持 Where/Select/OrderBy/Join 等
  • 💾 智能缓存 - SqlQuery<T> 泛型缓存,自动注册 EntityProvider
  • 🔍 自动发现 - 源生成器自动发现 SqlQuery<T> 和 SqlTemplate 中的实体类型

快速开始

dotnet add package Sqlx
// 1. 定义实体
[Sqlx, TableName("users")]
public class User
{
    [Key] public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

// 2. 定义仓储接口
public interface IUserRepository : ICrudRepository<User, long>
{
    [SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE age >= @minAge")]
    Task<List<User>> GetAdultsAsync(int minAge);
}

// 3. 实现仓储(代码自动生成)
[SqlDefine(SqlDefineTypes.SQLite)]
[RepositoryFor(typeof(IUserRepository))]
public partial class UserRepository(DbConnection connection) : IUserRepository { }

// 4. 使用
await using var conn = new SqliteConnection("Data Source=app.db");
var repo = new UserRepository(conn);
var adults = await repo.GetAdultsAsync(18);

重要说明: Sqlx 中有两个不同的 SqlTemplate

  • [SqlTemplate] 特性 (Sqlx.Annotations) - 用于标注接口方法,定义 SQL 模板
  • SqlTemplate (Sqlx) - 运行时类,用于调试查看生成的 SQL
using Sqlx;                    // SqlTemplate 类
using Sqlx.Annotations;        // [SqlTemplate] 特性

public interface IUserRepository
{
    // [SqlTemplate] 特性 - 标注方法执行查询
    [SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE id = @id")]
    Task<User?> GetByIdAsync(long id);
    
    // SqlTemplate 类 - 返回类型用于调试(不执行查询)
    [SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE id = @id")]
    SqlTemplate GetByIdSql(long id);
}

// 调试使用
var template = repo.GetByIdSql(123);
Console.WriteLine($"SQL: {template.Sql}");

SQL 模板占位符

占位符自动适配不同数据库方言:

占位符 说明 示例输出
{{table}} 表名(带方言引号) "users" (PostgreSQL)
{{columns}} 所有列名 id, name, age
{{columns --exclude Id}} 排除指定列 name, age
{{values --exclude Id}} 参数占位符 @name, @age
{{values --inline CreatedAt=CURRENT_TIMESTAMP}} 内联表达式(INSERT 默认值) @name, @age, CURRENT_TIMESTAMP
{{set --exclude Id}} UPDATE SET 子句 name = @name
{{set --inline Version=Version+1}} 内联表达式(UPDATE 计算字段) name = @name, version = version+1
{{where --object filter}} 对象条件查询 (name = @name AND age = @age)
{{if notnull=param}}...{{/if}} 条件包含 动态 SQL

内联表达式(Inline Expressions)

内联表达式允许在 SQL 中使用表达式、函数和字面量:

// UPDATE 示例:自动递增版本号
[SqlTemplate(@"
    UPDATE {{table}} 
    SET {{set --exclude Id,Version --inline Version=Version+1,UpdatedAt=CURRENT_TIMESTAMP}} 
    WHERE id = @id
")]
Task<int> UpdateAsync(long id, string name, string email);
// 生成: UPDATE [users] SET [name] = @name, [email] = @email, 
//       [version] = [version]+1, [updated_at] = CURRENT_TIMESTAMP WHERE id = @id

// INSERT 示例:设置默认值
[SqlTemplate(@"
    INSERT INTO {{table}} ({{columns --exclude Id}}) 
    VALUES ({{values --exclude Id --inline Status='pending',CreatedAt=CURRENT_TIMESTAMP}})
")]
Task<int> CreateAsync(string name, string description);
// 生成: INSERT INTO [tasks] ([name], [description], [status], [created_at]) 
//       VALUES (@name, @description, 'pending', CURRENT_TIMESTAMP)

支持的表达式:

  • 算术运算:Version=Version+1, Total=@quantity*@unitPrice
  • SQL 函数:CreatedAt=CURRENT_TIMESTAMP, Email=LOWER(TRIM(Email))
  • 字面量:Status='pending', Priority=0, IsActive=1
  • 复杂表达式:Result=COALESCE(NULLIF(Value,''),Default)

关键特性:

  • ✅ 使用属性名(PascalCase),自动转换为列名
  • ✅ 函数内的逗号被正确处理(如 COALESCE(Status,'pending')
  • ✅ 支持嵌套函数和深度括号
  • ✅ 跨数据库方言自动适配
  • ✅ 编译时解析,零运行时开销

各数据库生成的 SQL:

数据库 生成的 SQL
SQLite SELECT [id], [name] FROM [users] WHERE is_active = 1
PostgreSQL SELECT "id", "name" FROM "users" WHERE is_active = true
MySQL SELECT `id`, `name` FROM `users` WHERE is_active = 1

内置仓储接口

继承 ICrudRepository<TEntity, TKey> 获得 42 个标准方法(24 个查询 + 18 个命令):

查询方法(24 个)

  • 单实体查询:GetByIdAsync/GetById, GetFirstWhereAsync/GetFirstWhere
  • 列表查询:GetByIdsAsync/GetByIds, GetAllAsync/GetAll, GetWhereAsync/GetWhere
  • 分页查询:GetPagedAsync/GetPaged, GetPagedWhereAsync/GetPagedWhere
  • 存在性检查:ExistsByIdAsync/ExistsById, ExistsAsync/Exists
  • 计数:CountAsync/Count, CountWhereAsync/CountWhere

命令方法(18 个)

  • 插入:InsertAndGetIdAsync/InsertAndGetId, InsertAsync/Insert, BatchInsertAsync/BatchInsert
  • 更新:UpdateAsync/Update, UpdateWhereAsync/UpdateWhere, BatchUpdateAsync/BatchUpdate
  • 删除:DeleteAsync/Delete, DeleteByIdsAsync/DeleteByIds, DeleteWhereAsync/DeleteWhere, DeleteAllAsync/DeleteAll
public interface IUserRepository : ICrudRepository<User, long>
{
    // 继承 42 个标准方法,无需自定义即可使用
    
    // 自定义方法(仅在需要复杂查询时)
    [SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE name LIKE @pattern")]
    Task<List<User>> SearchByNameAsync(string pattern);
}

条件占位符

// 动态搜索:只在参数有值时添加条件
[SqlTemplate(@"
    SELECT {{columns}} FROM {{table}} WHERE 1=1 
    {{if notnull=name}}AND name LIKE @name{{/if}}
    {{if notnull=minAge}}AND age >= @minAge{{/if}}
")]
Task<List<User>> SearchAsync(string? name, int? minAge);

对象条件查询

使用 {{where --object}} 从字典自动生成 WHERE 条件(AOT 兼容):

// 定义查询方法
[SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE {{where --object filter}}")]
Task<List<User>> FilterAsync(IReadOnlyDictionary<string, object?> filter);

// 使用:只有非空值会生成条件
var filter = new Dictionary<string, object?>
{
    ["Name"] = "John",      // 生成: [name] = @name
    ["Age"] = 25,           // 生成: [age] = @age
    ["Email"] = null        // 忽略(null 值)
};
var users = await repo.FilterAsync(filter);
// 生成: SELECT ... WHERE ([name] = @name AND [age] = @age)

// 空字典返回 1=1(查询所有)
var all = await repo.FilterAsync(new Dictionary<string, object?>());
// 生成: SELECT ... WHERE 1=1

IQueryable 查询构建器

使用标准 LINQ 语法构建类型安全的 SQL 查询:

// 基本查询
var query = SqlQuery<User>.ForSqlite()
    .Where(u => u.Age >= 18 && u.IsActive)
    .OrderBy(u => u.Name)
    .Take(10);

var sql = query.ToSql();
// SELECT [id], [name], [age], [is_active] FROM [User] 
// WHERE ([age] >= 18 AND [is_active] = 1) 
// ORDER BY [name] ASC LIMIT 10

// 投影查询(匿名类型,完全 AOT 兼容)
var results = await SqlQuery<User>.ForPostgreSQL()
    .Where(u => u.Name.Contains("test"))
    .Select(u => new { u.Id, u.Name })
    .WithConnection(connection)
    .ToListAsync();

// JOIN 查询
var query = SqlQuery<User>.ForSqlite()
    .Join(SqlQuery<Order>.ForSqlite(),
        u => u.Id,
        o => o.UserId,
        (u, o) => new { u.Name, o.Total })
    .Where(x => x.Total > 100);

// 聚合函数
var maxAge = await SqlQuery<User>.ForSqlite()
    .WithConnection(connection)
    .WithReader(UserResultReader.Default)
    .MaxAsync(u => u.Age);

支持的 LINQ 方法:

  • Where, Select, OrderBy, ThenBy, Take, Skip
  • GroupBy, Distinct, Join, GroupJoin
  • Count, Min, Max, Sum, Average
  • First, FirstOrDefault, Any

支持的函数:

  • String: Contains, StartsWith, EndsWith, ToUpper, ToLower, Trim, Substring, Replace, Length
  • Math: Abs, Round, Floor, Ceiling, Sqrt, Pow, Min, Max

表达式查询(仓储模式)

// 在仓储中使用 LINQ 表达式
[SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE {{where --param predicate}}")]
Task<List<User>> GetWhereAsync(Expression<Func<User, bool>> predicate);

// 使用
var adults = await repo.GetWhereAsync(u => u.Age >= 18 && u.IsActive);

批量执行

var users = new List<User> { new() { Name = "Alice" }, new() { Name = "Bob" } };
var sql = "INSERT INTO users (name) VALUES (@name)";
await connection.ExecuteBatchAsync(sql, users, UserParameterBinder.Default);

连接和事务管理

连接获取优先级

源生成器按以下优先级查找 DbConnection:

方法参数 > 字段 > 属性 > 主构造函数

// 方式 1: 显式字段(推荐,优先级最高)
[SqlDefine(SqlDefineTypes.SQLite)]
[RepositoryFor(typeof(IUserRepository))]
public partial class UserRepository : IUserRepository
{
    private readonly SqliteConnection _connection;
    public DbTransaction? Transaction { get; set; }
    
    public UserRepository(SqliteConnection connection)
    {
        _connection = connection;
    }
}

// 方式 2: 属性(适合需要外部访问)
public partial class UserRepository : IUserRepository
{
    public SqliteConnection Connection { get; }
    public DbTransaction? Transaction { get; set; }
    
    public UserRepository(SqliteConnection connection)
    {
        Connection = connection;
    }
}

// 方式 3: 主构造函数(最简洁,自动生成)
public partial class UserRepository(SqliteConnection connection) : IUserRepository
{
    // 生成器自动生成:
    // private readonly SqliteConnection _connection = connection;
    // public DbTransaction? Transaction { get; set; }
}

// 方式 4: 方法参数(最灵活,优先级最高)
public interface IUserRepository
{
    // 使用类级别连接
    [SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE id = @id")]
    Task<User?> GetByIdAsync(long id);
    
    // 使用方法参数连接(覆盖类级别连接)
    [SqlTemplate("SELECT {{columns}} FROM {{table}} WHERE id = @id")]
    Task<User?> GetByIdWithConnectionAsync(DbConnection connection, long id);
}

事务支持

var repo = new UserRepository(connection);

using var transaction = connection.BeginTransaction();
repo.Transaction = transaction;

try
{
    await repo.InsertAsync(user1);
    await repo.UpdateAsync(user2);
    await repo.DeleteAsync(user3);
    
    transaction.Commit();
}
catch
{
    transaction.Rollback();
    throw;
}

自动生成规则

  • 如果用户未定义 Transaction 属性,生成器会自动生成
  • 如果用户未定义连接字段/属性,生成器会从主构造函数参数自动生成字段

性能对比

基于 BenchmarkDotNet 测试(.NET 10 LTS,SQLite 内存数据库):

小数据集性能(10-100条)- Web API 主要场景

数据量 Sqlx Dapper.AOT FreeSql Sqlx 优势
10条 42.19 μs 43.42 μs 49.64 μs 🥇 快 2.9% / 17.7%
100条 230.35 μs 233.76 μs 237.38 μs 🥇 快 1.5% / 3.1%
1000条 2,165.87 μs 2,172.08 μs 1,625.41 μs 🥇 快 0.3%

内存效率

数据量 Sqlx Dapper.AOT FreeSql Sqlx 优势
10条 4.68 KB 6.55 KB 8.67 KB 🥇 少 40% / 85%
100条 37 KB 45.66 KB 37.23 KB 🥇 少 23%
1000条 360.24 KB 432.38 KB 318.6 KB 🥇 少 20%

GC 压力(关键指标)

数据量 Sqlx Gen1 Dapper.AOT Gen1 FreeSql Gen1 Sqlx 优势
1000条 1.95 3.91 25.39 🥇 最低(FreeSql 的 1/13)

关键洞察

  • ✅ Sqlx 在小数据集(10-100条)上性能最优,这是 Web API 的主要场景
  • ✅ Sqlx 的 GC 压力最小,更适合长时间运行的应用
  • ✅ Sqlx 在所有场景下都比 Dapper.AOT 快,且内存效率更高
  • ⚠️ FreeSql 在大数据集(1000+条)上更快,但 Gen1 GC 是 Sqlx 的 13倍

详细数据见 性能基准测试AOT 性能测试

支持的数据库

数据库 方言枚举 状态
SQLite SqlDefineTypes.SQLite ✅ 完全支持
PostgreSQL SqlDefineTypes.PostgreSql ✅ 完全支持
MySQL SqlDefineTypes.MySql ✅ 完全支持
SQL Server SqlDefineTypes.SqlServer ✅ 完全支持
Oracle SqlDefineTypes.Oracle ✅ 完全支持
IBM DB2 SqlDefineTypes.DB2 ✅ 完全支持

推荐: .NET 10 (LTS) - 支持到 2028 年 11 月,性能最佳

更多文档

许可证

MIT License - 详见 LICENSE.txt

Product 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 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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.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
0.6.8 96 2/7/2026
0.6.7 81 2/5/2026
0.6.6 80 2/3/2026
0.6.5 97 1/23/2026
0.6.4 87 1/22/2026
0.6.3 86 1/22/2026
0.6.2 99 1/16/2026
0.6.1 84 1/15/2026
0.6.0 83 1/15/2026
0.5.0 107 1/11/2026
0.4.0 213 10/27/2025
0.3.0 284 10/2/2025
0.2.0 227 9/21/2025
0.1.4-dev 210 8/31/2025
0.1.3-dev 118 8/23/2025
0.1.2-dev 177 8/20/2025
0.1.1-dev 149 8/17/2025
0.1.0-dev 164 7/27/2025