目录

​编辑

一、SQLSugar 简介

二、SQLSugar 环境搭建

2.1 安装 SQLSugar

2.1.1 通过 Visual Studio NuGet 图形化界面安装

2.1.2 通过 NuGet 命令行安装

2.2 引用 SQLSugar 命名空间

三、SQLSugar 核心初始化配置

3.1 基础初始化(非 IOC 模式)

3.1.1 单数据库配置

3.1.2 多数据库配置

3.2 IOC 模式初始化(适用于ASP.NET Core)

3.2.1 配置服务(Program.cs/.NET 6+)

3.2.2 在控制器中注入使用

3.3 连接字符串配置(AppSettings.json)

四、实体类映射(ORM 核心)

4.1 特性映射(推荐)

4.1.1 常用特性说明

4.1.2 实体类示例

4.2 约定映射(默认)

4.3 导航属性配置

五、SQLSugar 常见查询举例与对应 SQL 实现

5.1 单表查询

5.1.1 查询所有数据(无条件)

5.1.2 根据主键查询单条数据

5.1.3 条件查询(单条件 / 多条件)

5.1.4 模糊查询(Like)

5.1.5 范围查询(In/Between)

5.1.6 排序查询(OrderBy)

5.1.7 限制结果集(Take/Skip)

5.1.8 分页查询

5.1.9 统计查询(Count/Sum/Avg/Max/Min)

5.1.10 分组统计查询(GroupBy)

5.2 多表联查

5.2.1 两表联查(左联:Left Join)

5.2.2 两表联查(内联:Inner Join)

5.2.3 三表联查(左联 + 内联)

5.3 子查询

5.3.1 子查询作为条件(Exists/In)

5.3.2 子查询作为结果集(From 子查询)

5.4 自定义 SQL 查询

5.4.1 执行查询 SQL(返回实体类 / 匿名对象)

5.4.2 带参数的自定义 SQL(防止 SQL 注入)

六、SQLSugar 详细使用指导

6.1 CRUD 操作完整示例(除查询外)

6.1.1 新增操作(Insert)

6.1.2 修改操作(Update)

6.1.3 删除操作(Delete)

6.2 事务处理

6.2.1 手动事务(推荐,灵活控制)

6.2.2 自动事务(简化代码,通过特性或方法)

6.3 缓存功能

6.3.1 基础缓存使用(内存缓存)

6.3.2 自定义 Redis 缓存

6.4 代码生成器

6.4.1 基础代码生成(生成实体类)

6.4.2 高级代码生成(生成仓储类 + 服务类)

七、SQLSugar 使用注意事项

7.1 连接与性能相关

7.2 实体类映射相关

7.3 查询相关


一、SQLSugar 简介

SQLSugar 是一款轻量级、高性能的 ORM(对象关系映射)框架,基于.NET 平台开发,支持多种数据库(如 SQL Server、MySQL、Oracle、SQLite、PostgreSQL 等)。它兼具了 EF(Entity Framework)的易用性和 Dapper 的高性能,提供了丰富的 API 接口,能轻松实现数据库的增删改查(CRUD)操作,同时支持复杂查询、事务处理、代码优先(Code First)、数据库优先(DB First)等功能,是.NET 开发者在项目开发中操作数据库的优质选择。

相比其他 ORM 框架,SQLSugar 具有以下优势:

  1. 性能优异:采用了高效的 SQL 生成机制和参数化查询,避免 SQL 注入问题,同时减少数据库交互次数,提升查询效率。
  1. 易用性强:API 设计简洁直观,学习成本低,开发者无需编写复杂的 SQL 语句,通过面向对象的方式即可操作数据库。
  1. 功能全面:支持单表查询、多表联查、子查询、分组统计、分页查询等各类查询场景,同时提供事务、缓存、日志、代码生成等辅助功能。
  1. 多数据库支持:只需修改连接字符串和数据库类型配置,即可在不同数据库之间无缝切换,降低项目的数据库迁移成本。
  1. 扩展性好:支持自定义 SQL、存储过程调用、函数调用等,满足复杂业务场景的需求。

二、SQLSugar 环境搭建

2.1 安装 SQLSugar

SQLSugar 可通过 NuGet 包管理器快速安装,支持.NET Framework 4.5+、.NET Core 2.0+、.NET 5/6/7/8 等版本。以下是两种常见的安装方式:

2.1.1 通过 Visual Studio NuGet 图形化界面安装
  1. 打开 Visual Studio,创建或打开一个.NET 项目(如控制台应用、ASP.NET Core Web 应用等)。
  1. 在 “解决方案资源管理器” 中,右键点击项目名称,选择 “管理 NuGet 程序包”。
  1. 在弹出的 NuGet 包管理器界面中,切换到 “浏览” 选项卡,在搜索框中输入 “SQLSugar”。
  1. 找到 “SQLSugarCore”(.NET Core/.NET 5 + 版本)或 “SQLSugar”(.NET Framework 版本),点击 “安装” 按钮,等待安装完成。
2.1.2 通过 NuGet 命令行安装

打开 Visual Studio 的 “程序包管理器控制台”(工具 -> NuGet 包管理器 -> 程序包管理器控制台),根据项目框架版本执行以下命令:

  • .NET Core/.NET 5+:
 

Install-Package SQLSugarCore

  • .NET Framework:
 

Install-Package SQLSugar

2.2 引用 SQLSugar 命名空间

安装完成后,在需要使用 SQLSugar 的代码文件中,引用以下命名空间:

 

using SqlSugar;

using SqlSugar.IOC; // 若使用IOC容器集成,需引用此命名空间

三、SQLSugar 核心初始化配置

在使用 SQLSugar 操作数据库前,需要先进行初始化配置,主要包括创建SqlSugarClient实例、设置连接字符串、配置数据库类型等。SqlSugarClient是 SQLSugar 的核心对象,所有数据库操作都通过该对象完成。

3.1 基础初始化(非 IOC 模式)

适用于小型项目或不需要依赖注入的场景,直接创建SqlSugarClient实例并配置相关参数。

3.1.1 单数据库配置

以 SQL Server 为例,基础初始化代码如下:

 

// 1. 创建连接配置对象

var connectionConfig = new ConnectionConfig

{

ConnectionString = "Server=localhost;Database=TestDB;Uid=sa;Pwd=123456;", // 数据库连接字符串

DbType = DbType.SqlServer, // 数据库类型(SqlServer、MySql、Oracle、Sqlite、PostgreSQL等)

IsAutoCloseConnection = true, // 是否自动关闭数据库连接(建议设置为true,避免连接泄露)

InitKeyType = InitKeyType.Attribute // 主键初始化方式(Attribute:通过实体类特性指定主键;Auto:自动识别主键)

};

// 2. 创建SqlSugarClient实例

SqlSugarClient db = new SqlSugarClient(connectionConfig);

// 3. (可选)配置日志输出(便于调试,查看生成的SQL语句)

db.Aop.OnLogExecuting = (sql, pars) =>

{

Console.WriteLine($"SQL语句:{sql}");

Console.WriteLine($"参数:{string.Join(",", pars.Select(p => $"{p.ParameterName}={p.Value}"))}");

};

3.1.2 多数据库配置

若项目中需要操作多个不同类型的数据库(如同时操作 SQL Server 和 MySQL),可通过ConnectionConfig的ConfigId属性区分不同数据库配置:

 

// 配置SQL Server数据库(ConfigId=1)

var sqlServerConfig = new ConnectionConfig

{

ConfigId = 1,

ConnectionString = "Server=localhost;Database=TestDB_SQLServer;Uid=sa;Pwd=123456;",

DbType = DbType.SqlServer,

IsAutoCloseConnection = true,

InitKeyType = InitKeyType.Attribute

};

// 配置MySQL数据库(ConfigId=2)

var mySqlConfig = new ConnectionConfig

{

ConfigId = 2,

ConnectionString = "Server=localhost;Database=TestDB_MySQL;Uid=root;Pwd=123456;Port=3306;",

DbType = DbType.MySql,

IsAutoCloseConnection = true,

InitKeyType = InitKeyType.Attribute

};

// 创建SqlSugarClient实例,传入多个连接配置

SqlSugarClient db = new SqlSugarClient(new List<ConnectionConfig> { sqlServerConfig, mySqlConfig });

// 使用不同数据库:通过ConfigId获取对应数据库的操作对象

var sqlServerDb = db.GetConnection(1); // SQL Server数据库操作对象

var mySqlDb = db.GetConnection(2); // MySQL数据库操作对象

3.2 IOC 模式初始化(适用于ASP.NET Core)

在ASP.NET Core 项目中,推荐使用 IOC(依赖注入)模式集成 SQLSugar,便于项目的解耦和维护。

3.2.1 配置服务(Program.cs/.NET 6+)
 

var builder = WebApplication.CreateBuilder(args);

// 1. 添加SQLSugar服务

builder.Services.AddSqlSugar(new IocConfig

{

ConnectionConfigs = new List<ConnectionConfig>

{

new ConnectionConfig

{

ConfigId = "MainDB", // 配置ID(自定义,用于区分不同数据库)

ConnectionString = builder.Configuration.GetConnectionString("MainDB"), // 从配置文件读取连接字符串

DbType = DbType.SqlServer,

IsAutoCloseConnection = true,

InitKeyType = InitKeyType.Attribute

}

},

Scope = ServiceLifetime.Scoped // 服务生命周期(Scoped:每个请求创建一个实例;Singleton:单例;Transient:每次获取创建一个实例)

});

// 2. 添加其他服务(如MVC控制器)

builder.Services.AddControllersWithViews();

var app = builder.Build();

// 后续中间件配置...

3.2.2 在控制器中注入使用
 

public class UserController : Controller

{

private readonly ISqlSugarClient _db; // 注入ISqlSugarClient接口

// 构造函数注入

public UserController(ISqlSugarClient db)

{

_db = db;

}

// 示例:查询用户列表

public IActionResult UserList()

{

var userList = _db.Queryable<User>().ToList();

return View(userList);

}

}

3.3 连接字符串配置(AppSettings.json)

为了便于项目配置管理,通常将连接字符串配置在AppSettings.json文件中(以ASP.NET Core 为例):

 

{

"Logging": {

"LogLevel": {

"Default": "Information",

"Microsoft.AspNetCore": "Warning"

}

},

"AllowedHosts": "*",

"ConnectionStrings": {

"MainDB": "Server=localhost;Database=TestDB;Uid=sa;Pwd=123456;", // SQL Server连接字符串

"MySqlDB": "Server=localhost;Database=TestDB_MySQL;Uid=root;Pwd=123456;Port=3306;" // MySQL连接字符串

}

}

读取连接字符串时,可通过IConfiguration接口获取:

 

// 在Program.cs中

var connectionString = builder.Configuration.GetConnectionString("MainDB");

// 在控制器或服务中(需注入IConfiguration)

private readonly IConfiguration _configuration;

public MyService(IConfiguration configuration)

{

_configuration = configuration;

}

public void Test()

{

var connectionString = _configuration.GetConnectionString("MySqlDB");

}

四、实体类映射(ORM 核心)

SQLSugar 通过实体类与数据库表进行映射,实体类的属性对应数据库表的字段。映射方式主要有两种:特性映射(通过实体类特性指定表名、字段名、主键、自增等)和约定映射(默认约定,如实体类名对应表名、属性名对应字段名)。

4.1 特性映射(推荐)

通过SqlSugar命名空间下的特性(如SugarTable、SugarColumn)明确指定实体类与数据库表的映射关系,灵活性高,适用于表名 / 字段名与实体类 / 属性名不一致的场景。

4.1.1 常用特性说明

特性

作用

[SugarTable("表名")]

指定实体类对应的数据库表名(若不指定,默认实体类名即为表名)。

[SugarColumn(IsPrimaryKey = true)]

指定该属性为表的主键。

[SugarColumn(IsIdentity = true)]

指定该属性为自增字段(仅支持整数类型主键)。

[SugarColumn(ColumnName = "字段名")]

指定属性对应的数据库字段名(若不指定,默认属性名即为字段名)。

[SugarColumn(IsNullable = true/false)]

指定字段是否允许为 NULL(默认根据属性类型判断,引用类型允许为 NULL)。

[SugarColumn(ColumnDescription = "字段描述")]

添加字段描述(生成表结构时会同步到数据库表字段的描述中)。

[SugarColumn(IsIgnore = true)]

忽略该属性,不参与数据库映射(即该属性不会对应表中的任何字段)。

[SugarColumn(Length = 50)]

指定字段长度(适用于字符串类型,如 VARCHAR (50))。

4.1.2 实体类示例

以 “用户表(Users)” 和 “订单表(Orders)” 为例,实体类定义如下:

 

using System;

using SqlSugar;

// 用户表实体类(对应数据库表:Users)

[SugarTable("Users")]

public class User

{

// 主键(自增)

[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "UserId")]

public int Id { get; set; }

// 用户名(字段名:UserName,长度50,非NULL)

[SugarColumn(ColumnName = "UserName", Length = 50, IsNullable = false)]

public string Name { get; set; }

// 年龄(字段名:Age,允许为NULL)

[SugarColumn(ColumnName = "Age", IsNullable = true)]

public int? Age { get; set; }

// 性别(字段名:Gender,长度10,允许为NULL)

[SugarColumn(ColumnName = "Gender", Length = 10, IsNullable = true)]

public string Gender { get; set; }

// 注册时间(字段名:RegisterTime,默认值为当前时间)

[SugarColumn(ColumnName = "RegisterTime", DefaultValue = "GETDATE()")]

public DateTime RegisterTime { get; set; }

// 忽略字段(不映射到数据库表)

[SugarColumn(IsIgnore = true)]

public string TempData { get; set; }

}

// 订单表实体类(对应数据库表:Orders)

[SugarTable("Orders")]

public class Order

{

// 订单ID(主键,自增)

[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "OrderId")]

public int Id { get; set; }

// 用户ID(外键,关联Users表的UserId)

[SugarColumn(ColumnName = "UserId", IsNullable = false)]

public int UserId { get; set; }

// 订单金额(字段名:OrderAmount)

[SugarColumn(ColumnName = "OrderAmount", IsNullable = false)]

public decimal Amount { get; set; }

// 订单状态(字段名:OrderStatus,1:待支付,2:已支付,3:已取消)

[SugarColumn(ColumnName = "OrderStatus", IsNullable = false)]

public int Status { get; set; }

// 订单创建时间(字段名:CreateTime)

[SugarColumn(ColumnName = "CreateTime")]

public DateTime CreateTime { get; set; }

// 导航属性(关联用户表,非数据库字段,需忽略)

[SugarColumn(IsIgnore = true)]

public User User { get; set; }

}

4.2 约定映射(默认)

若数据库表名与实体类名一致、表字段名与实体类属性名一致(大小写不敏感,如 “UserId” 与 “userId” 视为一致),则无需添加任何特性,SQLSugar 会自动完成映射。例如:

 

// 实体类名(User)对应表名(User),属性名(UserId、UserName等)对应字段名(UserId、UserName等)

public class User

{

// 主键(默认识别名为“Id”或“UserId”的属性为主键,若为整数类型,默认自增)

public int UserId { get; set; }

public string UserName { get; set; }

public int? Age { get; set; }

public DateTime RegisterTime { get; set; }

}

4.3 导航属性配置

导航属性用于表示实体类之间的关联关系(如一对一、一对多、多对多),SQLSugar 支持通过导航属性实现关联查询。例如,订单表(Order)与用户表(User)为一对多关系(一个用户可拥有多个订单),可通过以下方式配置导航属性:

 

// 用户表实体类(一对多:一个用户有多个订单)

[SugarTable("Users")]

public class User

{

[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "UserId")]

public int Id { get; set; }

[SugarColumn(ColumnName = "UserName")]

public string Name { get; set; }

// 导航属性:用户的所有订单(一对多)

[SugarColumn(IsIgnore = true)]

public List<Order> Orders { get; set; }

}

// 订单表实体类(多对一:多个订单属于一个用户)

[SugarTable("Orders")]

public class Order

{

[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "OrderId")]

public int Id { get; set; }

[SugarColumn(ColumnName = "UserId")]

public int UserId { get; set; }

[SugarColumn(ColumnName = "OrderAmount")]

public decimal Amount { get; set; }

// 导航属性:订单所属的用户(多对一)

[SugarColumn(IsIgnore = true)]

public User User { get; set; }

}

五、SQLSugar 常见查询举例与对应 SQL 实现

查询是数据库操作中最常用的场景,SQLSugar 提供了Queryable方法构建查询,支持单表查询、多表联查、子查询、分页查询、分组统计等各类查询需求。以下将结合实例,详细讲解常见查询的实现方式,并给出对应的 SQL 语句。

5.1 单表查询

单表查询是最基础的查询场景,主要通过db.Queryable<T>()方法获取查询对象,再结合Where、Select、OrderBy、Take、Skip等方法筛选、排序、限制结果集,最后通过ToList()、FirstOrDefault()等方法执行查询并返回结果。

5.1.1 查询所有数据(无条件)

需求:查询Users表中的所有用户数据。

C# 代码

 

// 方式1:查询所有字段(返回实体类列表)

var allUsers = db.Queryable<User>().ToList();

// 方式2:查询指定字段(返回匿名对象列表)

var userNames = db.Queryable<User>()

.Select(u => new { u.Id, u.Name, u.RegisterTime }) // 指定查询字段

.ToList();

对应 SQL 实现

  • 方式 1 对应 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

  • 方式 2 对应 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [RegisterTime] AS [RegisterTime]

FROM [Users]

5.1.2 根据主键查询单条数据

需求:根据UserId(主键)查询指定用户。

C# 代码

 

// 方式1:使用FindById方法(推荐,仅支持主键查询)

int userId = 1;

var userById = db.Queryable<User>().FindById(userId);

// 方式2:使用Where+FirstOrDefault方法

var userByWhere = db.Queryable<User>()

.Where(u => u.Id == userId) // 主键条件

.FirstOrDefault(); // 返回第一条数据,无数据则返回NULL

对应 SQL 实现

  • 方式 1 / 方式 2 对应 SQL(参数化查询,避免 SQL 注入):
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [UserId] = @Id1 -- @Id1=1

5.1.3 条件查询(单条件 / 多条件)

需求 1:查询年龄大于 20 的用户(单条件)。

C# 代码

 

var usersOver20 = db.Queryable<User>()

.Where(u => u.Age > 20) // 单条件:年龄>20

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [Age] > @Age1 -- @Age1=20

需求 2:查询年龄大于 20 且性别为 “男” 的用户(多条件:AND)。

C# 代码

 

var maleUsersOver20 = db.Queryable<User>()

.Where(u => u.Age > 20 && u.Gender == "男") // 多条件AND

.ToList();

// 或使用Where链式调用(效果相同)

var maleUsersOver20_2 = db.Queryable<User>()

.Where(u => u.Age > 20)

.Where(u => u.Gender == "男")

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [Age] > @Age1 AND [Gender] = @Gender1 -- @Age1=20, @Gender1='男'

需求 3:查询年龄大于 20 或注册时间在 2024 年之后的用户(多条件:OR)。

C# 代码

 

var targetUsers = db.Queryable<User>()

.Where(u => u.Age > 20 || u.RegisterTime >= new DateTime(2024, 1, 1)) // 多条件OR

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [Age] > @Age1 OR [RegisterTime] >= @RegisterTime1 -- @Age1=20, @RegisterTime1='2024-01-01 00:00:00'

5.1.4 模糊查询(Like)

需求:查询用户姓名中包含 “张” 字的用户。

C# 代码

 

// 方式1:使用Contains(自动拼接%,对应LIKE '%张%')

var usersWithZhang = db.Queryable<User>()

.Where(u => u.Name.Contains("张"))

.ToList();

// 方式2:使用StartsWith(对应LIKE '张%')

var usersStartWithZhang = db.Queryable<User>()

.Where(u => u.Name.StartsWith("张"))

.ToList();

// 方式3:使用 EndsWith(对应LIKE '%张')

var usersEndWithZhang = db.Queryable<User>()

.Where(u => u.Name.EndsWith("张"))

.ToList();

// 方式4:手动拼接%(适用于复杂模糊查询场景)

var usersLikeZhang = db.Queryable<User>()

.Where(u => SqlFunc.Like(u.Name, "%张%")) // 使用SqlFunc.Like方法

.ToList();

对应 SQL 实现

  • 方式 1 对应 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [UserName] LIKE @Name1 -- @Name1='%张%'

  • 方式 2 对应 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [UserName] LIKE @Name1 -- @Name1='张%'

  • 方式 3 对应 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [UserName] LIKE @Name1 -- @Name1='%张'

  • 方式 4 对应 SQL(与方式 1 相同):
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [UserName] LIKE @Name1 -- @Name1='%张%'

5.1.5 范围查询(In/Between)

需求 1:查询用户 ID 在 [1,3,5] 范围内的用户(In)。

C# 代码

 

List<int> userIds = new List<int> { 1, 3, 5 };

var usersInIds = db.Queryable<User>()

.Where(u => userIds.Contains(u.Id)) // 使用Contains实现In查询

.ToList();

// 或使用SqlFunc.In方法(效果相同)

var usersInIds_2 = db.Queryable<User>()

.Where(u => SqlFunc.In(u.Id, userIds))

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [UserId] IN (@Id1, @Id2, @Id3) -- @Id1=1, @Id2=3, @Id3=5

需求 2:查询注册时间在 2023 年 1 月 1 日至 2024 年 1 月 1 日之间的用户(Between)。

C# 代码

 

DateTime startDate = new DateTime(2023, 1, 1);

DateTime endDate = new DateTime(2024, 1, 1);

// 方式1:使用>=和<=实现Between

var usersBetweenDate = db.Queryable<User>()

.Where(u => u.RegisterTime >= startDate && u.RegisterTime <= endDate)

.ToList();

// 方式2:使用SqlFunc.Between方法

var usersBetweenDate_2 = db.Queryable<User>()

.Where(u => SqlFunc.Between(u.RegisterTime, startDate, endDate))

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

WHERE [RegisterTime] BETWEEN @RegisterTime1 AND @RegisterTime2 -- @RegisterTime1='2023-01-01 00:00:00', @RegisterTime2='2024-01-01 00:00:00'

5.1.6 排序查询(OrderBy)

需求:查询所有用户,先按注册时间降序排序(最新注册的在前),再按年龄升序排序(年龄小的在前)。

C# 代码

 

var sortedUsers = db.Queryable<User>()

.OrderBy(u => u.RegisterTime, OrderByType.Desc) // 降序排序(Desc)

.OrderBy(u => u.Age, OrderByType.Asc) // 升序排序(Asc,默认可省略)

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

ORDER BY [RegisterTime] DESC, [Age] ASC

5.1.7 限制结果集(Take/Skip)

需求 1:查询前 10 条用户数据(Take)。

C# 代码

 

var top10Users = db.Queryable<User>()

.Take(10) // 取前10条

.ToList();

对应 SQL(SQL Server)

 

SELECT TOP 10 [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

对应 SQL(MySQL)

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

LIMIT 10

需求 2:跳过前 5 条数据,查询后续的 10 条数据(Skip+Take,常用于分页的基础)。

C# 代码

 

var skip5Take10Users = db.Queryable<User>()

.Skip(5) // 跳过前5条

.Take(10) // 取后续10条

.ToList();

对应 SQL(SQL Server)

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM (

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime],

ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RowNum -- 临时排序字段

FROM [Users]

) AS Temp

WHERE Temp.RowNum > 5 AND Temp.RowNum <= 15 -- 5+10=15

对应 SQL(MySQL)

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

LIMIT 5, 10 -- 跳过5条,取10条(偏移量5,条数10)

5.1.8 分页查询

分页查询是项目中常用的查询场景,SQLSugar 提供了ToPageList方法,直接支持分页,无需手动计算Skip和Take,同时可获取总记录数。

需求:查询用户列表,每页显示 10 条数据,查询第 2 页的数据,并获取总记录数。

C# 代码

 

int pageIndex = 2; // 当前页码(从1开始)

int pageSize = 10; // 每页条数

int totalCount = 0; // 总记录数(输出参数)

// 方式1:使用ToPageList方法(推荐,自动计算分页,并返回总记录数)

var userPageList = db.Queryable<User>()

.OrderBy(u => u.RegisterTime, OrderByType.Desc) // 分页必须排序,否则结果不稳定

.ToPageList(pageIndex, pageSize, ref totalCount);

// 方式2:手动计算Skip和Take(适用于复杂场景)

var userPageList_2 = db.Queryable<User>()

.OrderBy(u => u.RegisterTime, OrderByType.Desc)

.Skip((pageIndex - 1) * pageSize) // 计算跳过的条数:(页码-1)*每页条数

.Take(pageSize)

.ToList();

// 手动获取总记录数

totalCount = db.Queryable<User>().Count();

Console.WriteLine($"总记录数:{totalCount}");

Console.WriteLine($"第{pageIndex}页数据条数:{userPageList.Count}");

对应 SQL(SQL Server,方式 1)

  • 查询分页数据的 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM (

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime],

ROW_NUMBER() OVER (ORDER BY [RegisterTime] DESC) AS RowNum

FROM [Users]

) AS Temp

WHERE Temp.RowNum > 10 AND Temp.RowNum <= 20 -- (2-1)*10=10,2*10=20

  • 获取总记录数的 SQL:
 

SELECT COUNT(1) FROM [Users]

对应 SQL(MySQL,方式 1)

  • 查询分页数据的 SQL:
 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users]

ORDER BY [RegisterTime] DESC

LIMIT 10, 10 -- (2-1)*10=10(偏移量),10(条数)

  • 获取总记录数的 SQL:
 

SELECT COUNT(1) FROM [Users]

5.1.9 统计查询(Count/Sum/Avg/Max/Min)

需求 1:统计Users表中的总用户数(Count)。

C# 代码

 

// 方式1:统计所有记录数

int totalUserCount = db.Queryable<User>().Count();

// 方式2:统计满足条件的记录数(年龄>20的用户数)

int userCountOver20 = db.Queryable<User>()

.Where(u => u.Age > 20)

.Count();

对应 SQL

  • 方式 1:SELECT COUNT(1) FROM [Users]
  • 方式 2:SELECT COUNT(1) FROM [Users] WHERE [Age] > @Age1(@Age1=20)

需求 2:统计所有订单的总金额(Sum)、平均金额(Avg)、最大金额(Max)、最小金额(Min)。

C# 代码

 

// 总金额(Sum)

decimal totalAmount = db.Queryable<Order>().Sum(o => o.Amount);

// 平均金额(Avg,返回double类型)

double avgAmount = db.Queryable<Order>().Avg(o => o.Amount);

// 最大金额(Max)

decimal maxAmount = db.Queryable<Order>().Max(o => o.Amount);

// 最小金额(Min)

decimal minAmount = db.Queryable<Order>().Min(o => o.Amount);

// 若结果可能为NULL(如表中无数据),建议使用可空类型接收

decimal? totalAmountNullable = db.Queryable<Order>().Sum<decimal?>(o => o.Amount);

对应 SQL

  • 总金额:SELECT SUM([OrderAmount]) FROM [Orders]
  • 平均金额:SELECT AVG(CAST([OrderAmount] AS FLOAT)) FROM [Orders](SQL Server 中需转换类型)
  • 最大金额:SELECT MAX([OrderAmount]) FROM [Orders]
  • 最小金额:SELECT MIN([OrderAmount]) FROM [Orders]
5.1.10 分组统计查询(GroupBy)

需求:按用户 ID 分组,统计每个用户的订单数量和订单总金额。

C# 代码

 

// 分组统计:按UserId分组,统计订单数和总金额

var userOrderStats = db.Queryable<Order>()

.GroupBy(o => o.UserId) // 按UserId分组

.Select(o => new

{

UserId = o.UserId,

OrderCount = SqlFunc.AggregateCount(o.Id), // 统计订单数

TotalAmount = SqlFunc.AggregateSum(o.Amount) // 统计总金额

})

.ToList();

// 筛选分组结果:仅显示订单数>=2的用户

var userOrderStatsFiltered = db.Queryable<Order>()

.GroupBy(o => o.UserId)

.Having(o => SqlFunc.AggregateCount(o.Id) >= 2) // 分组后筛选(Having)

.Select(o => new

{

UserId = o.UserId,

OrderCount = SqlFunc.AggregateCount(o.Id),

TotalAmount = SqlFunc.AggregateSum(o.Amount)

})

.ToList();

对应 SQL

  • 未筛选分组结果:
 

SELECT [UserId] AS [UserId],

COUNT([OrderId]) AS [OrderCount],

SUM([OrderAmount]) AS [TotalAmount]

FROM [Orders]

GROUP BY [UserId]

  • 筛选分组结果(Having):
 

SELECT [UserId] AS [UserId],

COUNT([OrderId]) AS [OrderCount],

SUM([OrderAmount]) AS [TotalAmount]

FROM [Orders]

GROUP BY [UserId]

HAVING COUNT([OrderId]) >= @Count1 -- @Count1=2

5.2 多表联查

多表联查用于查询多个关联表的数据,SQLSugar 支持Join方法实现内联(Inner Join)、左联(Left Join)、右联(Right Join)、全联(Full Join)等联查方式,联查条件通过On方法指定。

5.2.1 两表联查(左联:Left Join)

需求:查询所有用户及其关联的订单信息(若用户无订单,订单信息为 NULL)。

C# 代码

 

// 方式1:使用Join方法(Left Join)

var userOrderLeftJoin = db.Queryable<User>()

.LeftJoin<Order>((u, o) => u.Id == o.UserId) // 左联Orders表,联查条件:u.Id = o.UserId

.Select((u, o) => new

{

UserId = u.Id,

UserName = u.Name,

OrderId = o.Id,

OrderAmount = o.Amount,

OrderStatus = o.Status

})

.ToList();

// 方式2:通过导航属性联查(简化代码,需先配置导航属性)

var userOrderNav = db.Queryable<User>()

.Include(u => u.Orders) // 加载用户的Orders导航属性(左联)

.ToList();

对应 SQL(方式 1)

 

SELECT

u.[UserId] AS [UserId],

u.[UserName] AS [UserName],

o.[OrderId] AS [OrderId],

o.[OrderAmount] AS [OrderAmount],

o.[OrderStatus] AS [OrderStatus]

FROM [Users] u

LEFT JOIN [Orders] o ON u.[UserId] = o.[UserId]

5.2.2 两表联查(内联:Inner Join)

需求:查询有订单的用户及其订单信息(仅返回同时存在于 Users 和 Orders 表中的数据)。

C# 代码

 

var userOrderInnerJoin = db.Queryable<User>()

.InnerJoin<Order>((u, o) => u.Id == o.UserId) // 内联Orders表

.Select((u, o) => new

{

UserId = u.Id,

UserName = u.Name,

OrderId = o.Id,

OrderAmount = o.Amount

})

.ToList();

对应 SQL

 

SELECT

u.[UserId] AS [UserId],

u.[UserName] AS [UserName],

o.[OrderId] AS [OrderId],

o.[OrderAmount] AS [OrderAmount]

FROM [Users] u

INNER JOIN [Orders] o ON u.[UserId] = o.[UserId]

5.2.3 三表联查(左联 + 内联)

需求:假设有Users(用户表)、Orders(订单表)、OrderDetails(订单详情表),查询用户、订单及对应的订单详情信息(左联订单表,内联订单详情表)。

实体类补充

 

[SugarTable("OrderDetails")]

public class OrderDetail

{

[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "DetailId")]

public int Id { get; set; }

[SugarColumn(ColumnName = "OrderId")]

public int OrderId { get; set; }

[SugarColumn(ColumnName = "ProductName", Length = 100)]

public string ProductName { get; set; }

[SugarColumn(ColumnName = "ProductPrice")]

public decimal ProductPrice { get; set; }

[SugarColumn(ColumnName = "Quantity")]

public int Quantity { get; set; }

// 导航属性

[SugarColumn(IsIgnore = true)]

public Order Order { get; set; }

}

C# 代码

 

var userOrderDetailJoin = db.Queryable<User>()

.LeftJoin<Order>((u, o) => u.Id == o.UserId) // 左联Orders表

.InnerJoin<OrderDetail>((u, o, od) => o.Id == od.OrderId) // 内联OrderDetails表

.Select((u, o, od) => new

{

UserId = u.Id,

UserName = u.Name,

OrderId = o.Id,

OrderAmount = o.Amount,

ProductName = od.ProductName,

ProductPrice = od.ProductPrice,

Quantity = od.Quantity

})

.ToList();

对应 SQL

 

SELECT

u.[UserId] AS [UserId],

u.[UserName] AS [UserName],

o.[OrderId] AS [OrderId],

o.[OrderAmount] AS [OrderAmount],

od.[ProductName] AS [ProductName],

od.[ProductPrice] AS [ProductPrice],

od.[Quantity] AS [Quantity]

FROM [Users] u

LEFT JOIN [Orders] o ON u.[UserId] = o.[UserId]

INNER JOIN [OrderDetails] od ON o.[OrderId] = od.[OrderId]

5.3 子查询

子查询(嵌套查询)是指在一个查询语句内部包含另一个查询语句,SQLSugar 支持通过Queryable嵌套实现子查询,适用于复杂的查询场景。

5.3.1 子查询作为条件(Exists/In)

需求 1:查询存在订单的用户(使用 Exists 子查询)。

C# 代码

 

var usersWithOrders = db.Queryable<User>()

.Where(u => db.Queryable<Order>()

.Any(o => o.UserId == u.Id)) // Any对应Exists:判断是否存在满足条件的订单

.ToList();

对应 SQL

 

SELECT [UserId] AS [Id], [UserName] AS [Name], [Age] AS [Age], [Gender] AS [Gender], [RegisterTime] AS [RegisterTime]

FROM [Users] u

WHERE EXISTS (

SELECT 1 FROM [Orders] o WHERE o.[UserId] = u.[UserId]

)

需求 2:查询订单金额大于平均订单金额的订单(使用子查询获取平均金额)。

C# 代码

 

// 子查询:获取平均订单金额

var ordersOverAvgAmount = db.Queryable<Order>()

.Where(o => o.Amount > db.Queryable<Order>()

.Avg<decimal?>(o2 => o2.Amount)) // 子查询获取平均金额

.ToList();

对应 SQL

 

SELECT [OrderId] AS [Id], [UserId] AS [UserId], [OrderAmount] AS [Amount], [OrderStatus] AS [Status], [CreateTime] AS [CreateTime]

FROM [Orders] o

WHERE o.[OrderAmount] > (

SELECT AVG([OrderAmount]) FROM [Orders]

)

5.3.2 子查询作为结果集(From 子查询)

需求:查询每个用户的最新订单(先按用户分组获取最新订单 ID,再关联订单表查询详情)。

C# 代码

 

// 子查询:按用户分组,获取每个用户的最新订单ID(最大OrderId)

var subQuery = db.Queryable<Order>()

.GroupBy(o => o.UserId)

.Select(o => new { UserId = o.UserId, MaxOrderId = SqlFunc.AggregateMax(o.Id) });

// 主查询:关联子查询和订单表,获取最新订单详情

var latestOrders = db.Queryable(subQuery, "sub") // 子查询作为临时表,别名sub

.InnerJoin<Order>((sub, o) => sub.MaxOrderId == o.Id) // 关联订单表

.Select((sub, o) => new

{

UserId = sub.UserId,

OrderId = o.Id,

OrderAmount = o.Amount,

CreateTime = o.CreateTime

})

.ToList();

对应 SQL

 

SELECT

sub.[UserId] AS [UserId],

o.[OrderId] AS [OrderId],

o.[OrderAmount] AS [OrderAmount],

o.[CreateTime] AS [CreateTime]

FROM (

SELECT [UserId] AS [UserId], MAX([OrderId]) AS [MaxOrderId]

FROM [Orders]

GROUP BY [UserId]

) sub

INNER JOIN [Orders] o ON sub.[MaxOrderId] = o.[OrderId]

5.4 自定义 SQL 查询

对于特别复杂的查询场景(如多表嵌套、特殊函数调用等),若通过Queryable方法难以实现,可直接使用 SQLSugar 的自定义 SQL 查询功能,通过Ado.SqlQuery或Ado.SqlQuerySingle方法执行原生 SQL 语句。

5.4.1 执行查询 SQL(返回实体类 / 匿名对象)

需求:通过自定义 SQL 查询用户及其订单数量。

C# 代码

 

// 方式1:返回匿名对象(适用于无需定义实体类的场景)

string sql = @"

SELECT

u.UserId AS Id,

u.UserName AS Name,

COUNT(o.OrderId) AS OrderCount

FROM Users u

LEFT JOIN Orders o ON u.UserId = o.UserId

GROUP BY u.UserId, u.UserName

";

var userOrderCount = db.Ado.SqlQuery<dynamic>(sql); // dynamic类型接收匿名对象

// 方式2:返回实体类(需定义对应实体类)

// 定义接收结果的实体类

public class UserOrderCountDto

{

public int Id { get; set; }

public string Name { get; set; }

public int OrderCount { get; set; }

}

var userOrderCountDto = db.Ado.SqlQuery<UserOrderCountDto>(sql);

对应 SQL:与自定义 SQL 语句一致。

5.4.2 带参数的自定义 SQL(防止 SQL 注入)

需求:通过自定义 SQL 查询指定用户 ID 的订单信息(带参数)。

C# 代码

 

int targetUserId = 1;

string sqlWithParam = @"

SELECT

OrderId AS Id,

UserId,

OrderAmount AS Amount,

OrderStatus AS Status

FROM Orders

WHERE UserId = @UserId

";

// 方式1:使用匿名对象传递参数

var ordersByUserId1 = db.Ado.SqlQuery<Order>(sqlWithParam, new { UserId = targetUserId });

// 方式2:使用SugarParameter传递参数(适用于复杂参数场景)

var param = new SugarParameter("@UserId", targetUserId);

var ordersByUserId2 = db.Ado.SqlQuery<Order>(sqlWithParam, param);

对应 SQL

 

SELECT

OrderId AS Id,

UserId,

OrderAmount AS Amount,

OrderStatus AS Status

FROM Orders

WHERE UserId = @UserId -- @UserId=1

六、SQLSugar 详细使用指导

6.1 CRUD 操作完整示例(除查询外)

除了查询操作,SQLSugar 还提供了简洁的 API 实现新增(Create)、修改(Update)、删除(Delete)操作,以下结合实例讲解。

6.1.1 新增操作(Insert)

需求 1:新增单个用户。

C# 代码

 

var newUser = new User

{

Name = "李四",

Age = 25,

Gender = "男",

RegisterTime = DateTime.Now

};

// 方式1:新增并返回自增主键(适用于自增主键场景)

int newUserId = db.Insertable(newUser).ExecuteReturnIdentity(); // 返回新增用户的Id(自增主键)

// 方式2:新增并返回受影响行数(适用于非自增主键场景)

int affectedRows = db.Insertable(newUser).ExecuteCommand(); // 返回受影响的行数(1表示成功)

对应 SQL

 

INSERT INTO [Users] ([UserName], [Age], [Gender], [RegisterTime])

VALUES (@UserName1, @Age1, @Gender1, @RegisterTime1);

SELECT SCOPE_IDENTITY() AS [Id] -- SQL Server获取自增主键;MySQL为SELECT LAST_INSERT_ID()

需求 2:批量新增用户(高效,减少数据库交互次数)。

C# 代码

 

var userList = new List<User>

{

new User { Name = "王五", Age = 22, Gender = "女", RegisterTime = DateTime.Now },

new User { Name = "赵六", Age = 30, Gender = "男", RegisterTime = DateTime.Now },

new User { Name = "孙七", Age = 28, Gender = "女", RegisterTime = DateTime.Now }

};

// 批量新增(支持批量插入,自动优化SQL)

int totalAffectedRows = db.Insertable(userList).ExecuteCommand(); // 返回总受影响行数(3表示成功)

对应 SQL(SQL Server,批量插入优化)

 

INSERT INTO [Users] ([UserName], [Age], [Gender], [RegisterTime])

VALUES

(@UserName1, @Age1, @Gender1, @RegisterTime1),

(@UserName2, @Age2, @Gender2, @RegisterTime2),

(@UserName3, @Age3, @Gender3, @RegisterTime3)

6.1.2 修改操作(Update)

需求 1:修改单个用户信息(根据主键)。

C# 代码

 

var updateUser = new User

{

Id = 1, // 主键(必须指定,用于定位要修改的记录)

Name = "李四_修改", // 要修改的字段

Age = 26 // 要修改的字段

};

// 方式1:修改所有非NULL字段(默认)

int affectedRows1 = db.Updateable(updateUser).ExecuteCommand();

// 方式2:指定修改的字段(忽略其他字段)

int affectedRows2 = db.Updateable(updateUser)

.SetColumns(u => new User { Name = u.Name, Age = u.Age }) // 仅修改Name和Age字段

.ExecuteCommand();

// 方式3:根据条件修改(不依赖实体类主键)

int affectedRows3 = db.Updateable<User>()

.SetColumns(u => u.Age == 26) // 修改字段:Age=26

.Where(u => u.Id == 1) // 条件:Id=1

.ExecuteCommand();

对应 SQL

  • 方式 1 / 方式 2:
 

UPDATE [Users]

SET [UserName] = @UserName1, [Age] = @Age1

WHERE [UserId] = @Id1 -- @Id1=1, @UserName1='李四_修改', @Age1=26

  • 方式 3:
 

UPDATE [Users]

SET [Age] = @Age1

WHERE [UserId] = @Id1 -- @Id1=1, @Age1=26

需求 2:批量修改订单状态(将用户 ID 为 1 的所有订单状态改为 “已支付”)。

C# 代码

 

int targetUserId = 1;

int newStatus = 2; // 2:已支付

int affectedRows = db.Updateable<Order>()

.SetColumns(o => o.Status == newStatus)

.Where(o => o.UserId == targetUserId)

.ExecuteCommand();

对应 SQL

 

UPDATE [Orders]

SET [OrderStatus] = @Status1

WHERE [UserId] = @UserId1 -- @Status1=2, @UserId1=1

6.1.3 删除操作(Delete)

需求 1:根据主键删除单个用户。

C# 代码

 

int targetUserId = 1;

// 方式1:根据实体类主键删除

var deleteUser = new User { Id = targetUserId };

int affectedRows1 = db.Deleteable(deleteUser).ExecuteCommand();

// 方式2:直接根据主键值删除

int affectedRows2 = db.Deleteable<User>().In(targetUserId).ExecuteCommand();

// 方式3:根据条件删除

int affectedRows3 = db.Deleteable<User>()

.Where(u => u.Id == targetUserId)

.ExecuteCommand();

对应 SQL

 

DELETE FROM [Users] WHERE [UserId] = @Id1 -- @Id1=1

需求 2:批量删除用户(根据用户 ID 列表)。

C# 代码

 

List<int> deleteUserIds = new List<int> { 2, 3, 4 };

// 批量删除(In查询)

int affectedRows = db.Deleteable<User>().In(deleteUserIds).ExecuteCommand();

对应 SQL

 

DELETE FROM [Users] WHERE [UserId] IN (@Id1, @Id2, @Id3) -- @Id1=2, @Id2=3, @Id3=4

6.2 事务处理

事务用于保证一组数据库操作的原子性(要么全部成功,要么全部失败),SQLSugar 支持手动事务和自动事务两种方式。

6.2.1 手动事务(推荐,灵活控制)

需求:新增用户的同时,为该用户创建一条初始订单,若其中一个操作失败,回滚所有操作。

C# 代码

 

try

{

// 1. 开启事务

db.Ado.BeginTran();

// 2. 执行新增用户操作

var newUser = new User { Name = "钱八", Age = 24, Gender = "男", RegisterTime = DateTime.Now };

int newUserId = db.Insertable(newUser).ExecuteReturnIdentity();

// 3. 执行新增订单操作(关联新用户ID)

var newOrder = new Order

{

UserId = newUserId,

Amount = 100.50m,

Status = 1, // 1:待支付

CreateTime = DateTime.Now

};

db.Insertable(newOrder).ExecuteCommand();

// 4. 提交事务(所有操作成功,提交)

db.Ado.CommitTran();

Console.WriteLine("事务执行成功!");

}

catch (Exception ex)

{

// 5. 回滚事务(若有操作失败,回滚)

db.Ado.RollbackTran();

Console.WriteLine($"事务执行失败,已回滚:{ex.Message}");

}

6.2.2 自动事务(简化代码,通过特性或方法)

需求:在ASP.NET Core 控制器中,通过特性自动开启事务。

C# 代码

 

// 1. 注册事务服务(Program.cs)

builder.Services.AddSqlSugarTransaction();

// 2. 在控制器方法中使用[Transaction]特性

[ApiController]

[Route("api/[controller]")]

public class UserController : ControllerBase

{

private readonly ISqlSugarClient _db;

public UserController(ISqlSugarClient db)

{

_db = db;

}

[HttpPost("AddUserAndOrder")]

[Transaction] // 自动开启事务,方法执行成功自动提交,失败自动回滚

public IActionResult AddUserAndOrder(User user, Order order)

{

// 新增用户

int newUserId = _db.Insertable(user).ExecuteReturnIdentity();

// 新增订单

order.UserId = newUserId;

_db.Insertable(order).ExecuteCommand();

return Ok("操作成功!");

}

}

6.3 缓存功能

SQLSugar 提供了内置缓存功能,支持将查询结果缓存到内存中,减少数据库查询次数,提升系统性能。缓存默认使用内存缓存,也支持自定义缓存(如 Redis)。

6.3.1 基础缓存使用(内存缓存)

需求:查询用户列表并缓存 10 分钟,10 分钟内再次查询时直接从缓存获取。

C# 代码

 

// 方式1:使用WithCache方法设置缓存(缓存Key自动生成)

var userList1 = db.Queryable<User>()

.WithCache(600) // 缓存时间:600秒(10分钟)

.ToList();

// 方式2:自定义缓存Key(便于手动清除缓存)

string cacheKey = "UserList_CacheKey";

var userList2 = db.Queryable<User>()

.WithCache(600, cacheKey) // 自定义缓存Key

.ToList();

// 手动清除缓存(当数据更新时,需清除对应缓存)

db.CacheService.Remove(cacheKey); // 清除指定Key的缓存

// db.CacheService.Clear(); // 清除所有缓存

6.3.2 自定义 Redis 缓存

需求:将查询结果缓存到 Redis 中,适用于分布式系统。

C# 代码

 

// 1. 实现ICacheService接口(Redis缓存实现)

public class RedisCacheService : ICacheService

{

private readonly IDistributedCache _redisCache;

public RedisCacheService(IDistributedCache redisCache)

{

_redisCache = redisCache;

}

// 添加缓存

public void Add<V>(string key, V value, int cacheDurationInSeconds)

{

var options = new DistributedCacheEntryOptions

{

AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(cacheDurationInSeconds)

};

string jsonValue = JsonSerializer.Serialize(value);

_redisCache.SetString(key, jsonValue, options);

}

// 获取缓存

public V Get<V>(string key)

{

string jsonValue = _redisCache.GetString(key);

return string.IsNullOrEmpty(jsonValue) ? default : JsonSerializer.Deserialize<V>(jsonValue);

}

// 移除缓存

public void Remove(string key)

{

_redisCache.Remove(key);

}

// 清除所有缓存(Redis不建议批量清除,可根据实际需求实现)

public void Clear()

{

// Redis批量清除需通过KEYS命令,生产环境慎用,此处省略实现

}

}

// 2. 注册Redis缓存服务(Program.cs)

builder.Services.AddStackExchangeRedisCache(options =>

{

options.Configuration = "localhost:6379"; // Redis连接字符串

});

builder.Services.AddScoped<ICacheService, RedisCacheService>();

// 3. 使用Redis缓存查询

var userList = db.Queryable<User>()

.WithCache(600, "UserList_RedisKey") // 使用Redis缓存

.ToList();

6.4 代码生成器

SQLSugar 提供了代码生成器功能,可根据数据库表结构自动生成实体类、仓储类、服务类等代码,减少重复编码工作,提升开发效率。

6.4.1 基础代码生成(生成实体类)

C# 代码

 

// 1. 创建代码生成器配置

var codeConfig = new CodeGeneratorConfig

{

ConnectionString = "Server=localhost;Database=TestDB;Uid=sa;Pwd=123456;",

DbType = DbType.SqlServer,

OutputDir = @"D:\CodeGeneratorOutput", // 代码输出目录

Namespace = "TestProject.Entities", // 实体类命名空间

GenerateNullableReferenceType = true, // 生成可空引用类型(.NET 6+支持)

EntityNameFormat = "{0}", // 实体类名格式({0}表示表名)

ColumnNameFormat = "{0}" // 属性名格式({0}表示字段名)

};

// 2. 创建代码生成器

var codeGenerator = new CodeGenerator(codeConfig);

// 3. 生成实体类(生成所有表的实体类)

codeGenerator.GenerateEntities();

// 4. (可选)生成指定表的实体类

codeGenerator.GenerateEntities(new List<string> { "Users", "Orders" }); // 仅生成Users和Orders表的实体类

Console.WriteLine("代码生成完成!");

6.4.2 高级代码生成(生成仓储类 + 服务类)

C# 代码

 

// 配置代码生成器

var codeConfig = new CodeGeneratorConfig

{

ConnectionString = "Server=localhost;Database=TestDB;Uid=sa;Pwd=123456;",

DbType = DbType.SqlServer,

OutputDir = @"D:\CodeGeneratorOutput",

Namespace = "TestProject",

// 生成仓储类(Repository)

GenerateRepository = true,

RepositoryNamespace = "TestProject.Repositories",

// 生成服务类(Service)

GenerateService = true,

ServiceNamespace = "TestProject.Services"

};

var codeGenerator = new CodeGenerator(codeConfig);

// 生成实体类、仓储类、服务类

codeGenerator.GenerateAll(); // 生成所有支持的代码类型

Console.WriteLine("所有代码生成完成!");

七、SQLSugar 使用注意事项

7.1 连接与性能相关

  1. 自动关闭连接:初始化SqlSugarClient时,务必将IsAutoCloseConnection设置为true,避免数据库连接泄露。若设置为false,需手动调用db.Close()关闭连接。
  1. SqlSugarClient实例生命周期
    • 非 IOC 模式:建议每个请求创建一个SqlSugarClient实例,使用完毕后自动关闭(依赖IsAutoCloseConnection=true),避免单例实例导致的线程安全问题。
    • IOC 模式:在ASP.NET Core 中,推荐使用Scoped生命周期(每个请求一个实例),避免Singleton(单例)导致的线程安全问题。
  1. 批量操作优化:批量新增、修改、删除时,使用 SQLSugar 提供的批量 API(如Insertable<List<T>>、Updateable<T>.In),避免循环调用单条操作,减少数据库交互次数。
  1. 避免过度查询:查询时仅获取需要的字段(使用Select指定字段),避免Select *查询不必要的字段,减少数据传输量和数据库负担。

7.2 实体类映射相关

  1. 主键与自增配置
    • 主键必须通过[SugarColumn(IsPrimaryKey = true)]明确指定,否则 SQLSugar 无法识别主键,导致修改、删除操作失败。
    • 自增字段需同时设置IsIdentity = true,且字段类型必须为整数类型(int、long 等),非整数类型无法支持自增。
  1. 字段类型匹配:实体类属性类型需与数据库表字段类型匹配,例如:
    • 数据库中的VARCHAR/NVARCHAR类型对应 C# 中的string类型。
    • 数据库中的DECIMAL类型对应 C# 中的decimal类型(避免使用double,防止精度丢失)。
    • 数据库中的DATETIME/DATETIME2类型对应 C# 中的DateTime类型。
  1. 导航属性忽略:导航属性(如User.Orders、Order.User)仅用于关联查询,不对应数据库表字段,需通过[SugarColumn(IsIgnore = true)]标记为忽略,否则会导致映射错误。
  1. 表名 / 字段名大小写:SQLSugar 默认不区分表名和字段名的大小写(如 “Users” 与 “users” 视为一致),但部分数据库(如 MySQL)默认区分大小写,需确保实体类特性指定的表名 / 字段名与数据库一致。

7.3 查询相关

  1. 分页必须排序:使用ToPageList进行分页查询时,必须通过OrderBy指定排序字段,否则数据库返回的结果顺序不稳定,导致分页数据重复或缺失。
  1. 子查询性能:复杂子查询可能导致性能问题,建议优先使用联查(Join)替代子查询,或通过索引优化子查询条件字段。
  1. 模糊查询优化:使用Like '%关键词%'(对应Contains)会导致索引失效,若需优化性能,可考虑:
    • 使用Like '关键词%'(对应StartsWith),可利用字段的前缀索引。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97518.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97518.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97518.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python与Rust语法对比详解:从入门到精通

Python与Rust语法对比详解&#xff1a;从入门到精通 前言 Python和Rust作为当今最受关注的编程语言&#xff0c;分别代表了动态类型和静态类型语言的典型特征。本文将从语法层面深入对比这两种语言&#xff0c;帮助开发者理解它们的设计理念和使用场景。1. 基础语法结构 1.1 He…

视频加水印_带gif 加动态水印 gif水印 视频浮动水印

如果你有一个视频&#xff0c;你想给它加一个水印&#xff0c;让水印浮动&#xff0c;而且加的还是 GIF 动态图片水印&#xff0c;那么你可以使用这个工具。首先把你的两个文件拖进来&#xff0c;然后点击第三个按钮。加好了&#xff0c;打开看一下&#xff0c;我们看到这个水印…

C# 字符和字符串

原文&#xff1a;C# 字符和字符串_w3cschool 请勿将文章标记为付费&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; C&#xff03;字符和字符串 C&#xff03;的 char 类型别名 System.Char 类型表示 Unicode 字符。 在单引号中指定char字面值&#xff1a; …

IntelliJ IDEA 反编译JAR包记录

本文记录了使用 IntelliJ IDEA 内置反编译工具对 JAR 包进行反编译的详细步骤&#xff0c;方便日后快速参考和使用。 &#x1f6e0;️ 工具准备 反编译工具使用的是 IntelliJ IDEA 内置的 Java 反编译器&#xff0c;无需额外安装其他工具。 工具路径&#xff1a; /Applications…

KingbaseES JDBC 驱动详解:连接、配置与最佳实践

目录KingbaseES JDBC 驱动详解&#xff1a;连接、配置与最佳实践引言一、JDBC 基础与 KingbaseES 实现1.1 JDBC 技术概述1.2 KingbaseES JDBC 驱动特点二、环境配置与驱动获取2.1 驱动包选择与依赖管理2.2 国密算法支持2.3 驱动版本信息获取三、数据库连接管理3.1 使用 DriverM…

破解 Aspose.Words 24.12,跳过 License 校验,实现 HTML 向 Word/PDF 的转换,附带 Demo。

说明 在Java生态中处理Office文档时&#xff0c;开发人员常面临格式兼容性和功能完整性的挑战。商业组件Aspose以其卓越的文档处理能力成为企业级解决方案之一&#xff0c;支持Word、Excel、PDF等多种格式的精准转换与操作。 请勿用于商业用途&#xff0c;若侵权请联系我。 参考…

php连接rabbitmq例子

首先确保安装好了Rabbitmq服务器。1.新建一个空白php项目&#xff0c;安装php客户端库&#xff1a;composer require php-amqplib/php-amqplib2.生产者然后添加生产者代码 (producer.php)<?php require_once __DIR__ . /vendor/autoload.php;use PhpAmqpLib\Connection\AMQ…

Docker Swarm vs Kubernetes vs Nomad:容器编排方案对比与选型建议

Docker Swarm vs Kubernetes vs Nomad&#xff1a;容器编排方案对比与选型建议 在微服务和云原生时代&#xff0c;容器编排成为支持大规模容器化应用的关键技术。本文将从问题背景、方案对比、优缺点分析、选型建议以及实际应用效果验证五个方面&#xff0c;对Docker Swarm、Ku…

似然函数对数似然函数负对数似然函数

目录1. 似然函数的定义2. 对数似然函数的定义3. 负对数似然函数的定义4. 负对数似然函数的优化5. 具体应用示例5.1 逻辑回归中的负对数似然函数5.2 优化逻辑回归的负对数似然函数1. 似然函数的定义 似然函数L(θ∣X)L(\theta | X)L(θ∣X)是在给定参数θ\thetaθ 下&#xff0…

鸿蒙地址选择库(ArkTs UI)

功能点&#xff1a;支持三级联动、点击确认返回省市区code及name&#xff08;安心&#xff09;、布局可以高度自定义 实现&#xff1a;TextPicker读取本地json&#xff08;也可用第三方的json 不过需要自行调整了&#xff09; 先上图吧、废话下面再说&#xff1a; 凑和看吧、…

YOLO 目标检测:数据集构建(LabelImg 实操)、评估指标(mAP/IOU)、 NMS 后处理

文章目录基本知识介绍1.视觉处理三大任务2.训练、验证、测试、推理3.数据集3.1 数据集格式3.2 数据集标注4.上游任务和下游任务YOLO指标1.真实框&#xff08;Ground Truth Box&#xff09;与边界框&#xff08;Bounding Box&#xff09;2.交并比&#xff08;IOU&#xff09;3.置…

进程状态 —— Linux内核(Kernel)

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录进…

计算机视觉与深度学习 | 低照度图像处理算法综述:发展、技术与趋势

文章目录 一、发展历程:从传统模型到智能融合 (一)传统模型构建阶段(1970s-2016) (二)深度学习应用阶段(2017-2020) (三)硬件-算法协同阶段(2021至今) 二、技术分类与性能对比 (一)传统方法体系 (二)深度学习方法 1. 监督学习模型 2. 无监督/自监督方法 3. 混…

责任链模式实践-开放银行数据保护及合规

责任链模式介绍什么是责任链模责任链模式是一种行为设计模式&#xff0c; 允许你将请求沿着处理者链进行发送。 收到请求后&#xff0c; 每个处理者均可对请求进行处理&#xff0c; 或将其传递给链上的下个处理者。责任链模式结构伪代码基于责任链的开放银行数据保护及合规实践…

npm install --global @dcloudio/uni-cli 时安装失败

这个日志显示在执行 npm install --global dcloudio/uni-cli 时安装失败&#xff0c;核心错误是 UNABLE_TO_GET_GET_ISSUER_CERT_LOCALLY&#xff08;无法获取本地颁发者证书&#xff09;&#xff0c;属于 HTTPS 证书验证失败 问题。错误原因npm 访问官方 registry&#xff08;…

吱吱企业通讯软件可私有化部署,构建安全可控的通讯办公平台

在当今激烈的市场竞争环境中&#xff0c;企业通讯已成为制胜的关键因素。吱吱作为一款专为企业管理设计的IM即时办公通讯软件&#xff0c;提供了高度安全的通讯办公环境&#xff0c;确保信息在内部流通的安全性与高效性&#xff0c;为企业数字化转型奠定了坚实的基础。 一、私有…

暄桐:唯有认真思考过死亡,才足以应对日常

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;皆在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。初听庄子在妻子离世后“鼓…

目标检测领域基本概念

基于提议的方法&#xff0c;也常被称为两阶段 (Two-stage) 方法&#xff0c;是目标检测领域的经典范式。它们将目标检测任务分解为两个主要步骤&#xff1a;阶段一&#xff1a;区域提议 (Region Proposal Generation) 目标&#xff1a; 在图像中生成一系列可能包含物体的候选区…

【开题答辩全过程】以 基于SpringBoot的流浪猫狗领养系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

扣子(coze)实践指南进阶篇——创建工作流,并将工作流接入智能体

大家好&#xff0c;欢迎阅读这份《智能体&#xff08;AIAgent&#xff09;开发指南》&#xff01; 在大模型和智能体快速发展的今天&#xff0c;很多朋友希望学习如何从零开始搭建一个属于自己的智能体。本教程的特点是 完全基于国产大模型与火山推理引擎实现&#xff0c;不用翻…