C#常用类库-详解SqlSugar
在C#企业级开发中,数据持久层是系统的核心基石------无论是简单的单表CRUD,还是复杂的多表联查、事务管理、分表分库,都需要一款高效、灵活、易用的ORM(对象关系映射)框架,来简化数据库操作、降低开发成本、提升系统性能。.NET生态中ORM框架众多,EF Core(微软官方)、Dapper(轻量高效)、NHibernate(功能全面)各有优势,但在"性能、灵活性、易用性"三者的平衡上,SqlSugar脱颖而出。
SqlSugar是一款基于.NET的轻量级、高性能ORM框架,凭借"零配置、语法简洁、性能接近原生SQL、支持多种数据库、功能全面"的核心优势,成为国内.NET开发者最喜爱的ORM框架之一。它既具备EF Core的便捷性(无需手动编写SQL),又拥有Dapper的高性能,同时支持动态SQL、事务、分页、分表分库、导航属性、缓存等企业级必备功能,适配从简单项目到大型分布式系统的各类场景。
本文将从基础概念→核心定位→环境搭建→基础CRUD→高级特性→企业级封装→性能优化→避坑指南,全方位、有深度地解析SqlSugar,结合实际开发场景(单表操作、多表联查、事务管理、批量操作等),帮你彻底掌握这款ORM"神器",真正做到"少写SQL、多做业务"。
一、前言:SqlSugar的定位与核心价值
在讲解SqlSugar之前,我们先明确三个核心问题:SqlSugar解决了什么痛点?它与EF Core、Dapper等主流ORM的差异是什么?为什么企业级开发中越来越多的开发者选择SqlSugar?这是理解其设计理念、合理选型的基础。
1. 核心痛点:传统数据库操作与主流ORM的弊端
日常开发中,无论是使用原生ADO.NET,还是主流ORM框架,在企业级场景下都会遇到诸多痛点,尤其是在性能、灵活性和易用性的平衡上:
-
原生ADO.NET:代码冗余,维护成本高:手动编写SQL语句、创建SqlConnection、SqlCommand、DataReader,频繁处理数据库连接的开启与关闭,代码冗余且易出错;SQL语句与业务代码耦合,修改SQL需改动业务代码,维护成本高;缺乏参数化查询,易引发SQL注入安全问题。
-
EF Core:性能损耗,灵活性不足:微软官方ORM,语法简洁、支持LINQ查询,无需手动编写SQL,但底层会自动生成SQL语句,复杂查询场景下生成的SQL冗余、效率低,性能损耗明显;动态SQL支持薄弱,复杂业务场景下需编写原生SQL混合使用,灵活性不足;数据库迁移功能虽便捷,但复杂场景下易出现迁移失败问题。
-
Dapper:轻量高效,但功能简陋:轻量级ORM,性能接近原生SQL,支持原生SQL查询,灵活性强,但功能相对简陋,缺乏导航属性、自动分页、分表分库等企业级功能;需要手动进行实体与数据的映射,复杂查询场景下代码编写繁琐,开发效率较低。
-
其他ORM:生态不完善,学习成本高:如NHibernate,功能全面但配置复杂、学习成本高,生态活跃度低,适配.NET Core/.NET 6+的速度较慢;部分小众ORM缺乏稳定更新和完善的文档,生产环境使用风险高。
而SqlSugar的核心设计理念就是"平衡性能、灵活性与易用性",既解决了原生ADO.NET的代码冗余问题,又弥补了EF Core的性能损耗和Dapper的功能不足,同时做到零配置、低学习成本,让开发者既能快速开发,又能兼顾系统性能。
2. SqlSugar的核心定位
SqlSugar是一款**.NET平台的轻量级、高性能、功能全面的ORM框架**,核心目标是"让数据库操作更简单、更高效、更灵活"。它采用"面向对象"的设计思想,将数据库表映射为C#实体类,通过链式API或LINQ语法,实现数据库操作的"无SQL化",同时保留原生SQL的灵活性,支持按需切换操作方式。
SqlSugar的核心优势可概括为6点,也是它区别于其他ORM的关键:
-
高性能:底层优化完善,查询性能接近原生SQL,远超EF Core,与Dapper持平;支持批量操作、延迟加载、缓存等性能优化机制,高并发场景下表现优异。
-
零配置:无需复杂的XML配置或注解,仅需配置数据库连接字符串,即可实现实体与数据库表的自动映射,开箱即用。
-
语法简洁:采用链式API设计,代码可读性高,CRUD操作一行代码即可完成;支持LINQ查询,也支持原生SQL混合使用,灵活适配各类场景。
-
功能全面:支持单表CRUD、多表联查、子查询、事务管理、批量操作、分页、分表分库、导航属性、缓存、数据库迁移、SQL注入防护等企业级必备功能。
-
多数据库支持:无缝支持SQL Server、MySQL、Oracle、PostgreSQL、SQLite、达梦、人大金仓等主流数据库,切换数据库无需修改业务代码,仅需修改连接字符串和数据库类型。
-
低学习成本:API设计简洁直观,文档完善,上手快速,熟悉C#基础即可快速掌握,无需深入学习复杂的ORM设计理念。
3. SqlSugar vs EF Core vs Dapper(核心差异对比)
为了更清晰地体现SqlSugar的优势,我们从"性能、易用性、功能、灵活性"等核心维度,与EF Core、Dapper进行对比,帮助大家合理选型:
| 对比维度 | SqlSugar | EF Core | Dapper |
|---|---|---|---|
| 性能表现 | 极高,接近原生SQL,批量操作、查询优化优异 | 中等,复杂查询生成冗余SQL,性能损耗明显 | 极高,轻量无冗余,性能与SqlSugar持平 |
| 易用性 | 极高,零配置,链式API+LINQ,上手快速 | 高,LINQ语法简洁,但复杂配置需学习成本 | 中等,需手动编写SQL,实体映射繁琐 |
| 功能全面性 | 全面,支持CRUD、联查、事务、分页、分表、缓存、迁移等 | 全面,但部分功能(如分表)需额外扩展 | 简陋,仅支持基础CRUD和原生SQL,无导航属性、分表等功能 |
| 灵活性 | 极高,支持链式API、LINQ、原生SQL混合使用,动态SQL便捷 | 中等,复杂场景需混合原生SQL,动态SQL支持薄弱 | 极高,完全支持原生SQL,可灵活控制所有数据库操作 |
| 多数据库支持 | 支持所有主流数据库,切换便捷,适配性好 | 支持主流数据库,但部分数据库特性适配不足 | 支持主流数据库,但需手动适配不同数据库的SQL语法 |
| 学习成本 | 低,API直观,文档完善,上手快 | 中,需学习LINQ、迁移、依赖注入等相关知识 | 低,但需熟悉SQL语法,手动处理映射逻辑 |
| 企业级适配 | 完美适配,支持分表分库、缓存、事务等企业级场景 | 适配,但性能和灵活性在高并发场景下不足 | 需二次封装,才能适配企业级复杂场景 |
| 选型建议(结合实际场景): |
-
小型项目、快速原型开发,且团队熟悉LINQ,无需复杂功能,可选择EF Core,微软官方维护,生态稳定。
-
高性能要求、复杂SQL场景,且团队熟悉SQL语法,可选择Dapper,轻量高效,灵活性强,但需手动封装功能。
-
企业级开发、高并发场景、需要兼顾易用性与性能,且需分表分库、缓存等功能,优先选择SqlSugar,零配置、功能全面、性能优异,大幅提升开发效率。
-
多数据库适配场景(如同时支持MySQL和SQL Server),优先选择SqlSugar,切换数据库无需修改业务代码。
4. 版本与安装
SqlSugar最新稳定版本为5.1.4.10(本文基于此版本讲解,适配.NET 6+,向下兼容.NET Core 3.1+、.NET Framework 4.6.1+),核心包体积小(仅几MB),无过多依赖,安装方式通过NuGet实现,根据项目类型和数据库类型选择对应的包。
常用安装包(按需选择):
-
核心包(必装):
Install-Package SqlSugarCore(.NET CLI:dotnet add package SqlSugarCore)------ 提供SqlSugar核心功能(ORM映射、CRUD、事务、分页等),适配.NET Core/.NET 5+。 -
.NET Framework版本:
Install-Package SqlSugar------ 适配.NET Framework 4.6.1+。 -
数据库驱动包(按需):
-
SQL Server:无需额外安装(核心包已集成)。
-
MySQL:
Install-Package MySqlConnector(推荐)或Install-Package MySql.Data。 -
Oracle:
Install-Package Oracle.ManagedDataAccess.Core。 -
PostgreSQL:
Install-Package Npgsql。 -
SQLite:
Install-Package Microsoft.Data.Sqlite。
-
-
扩展包(按需):
-
分页扩展:
Install-Package SqlSugar.Extensions.PagedList(简化分页操作)。 -
缓存扩展:
Install-Package SqlSugar.Cache.Redis(Redis缓存支持)。 -
数据库迁移扩展:
Install-Package SqlSugar.Migration(自动生成数据库表、迁移脚本)。
-
安装完成后,引入核心命名空间即可使用:using SqlSugar;
注意:SqlSugar 5.x版本与4.x版本API有少量差异(如数据库初始化方式、分页方法),本文基于最新5.x版本讲解,避免使用过时API(如旧版本的DbHelper已废弃)。
二、基础用法:从零开始使用SqlSugar(核心场景)
SqlSugar的核心流程分为3步:初始化SqlSugarClient→定义实体类(与数据库表映射)→执行CRUD操作。基础用法覆盖5个核心场景:SqlSugarClient初始化、实体映射、单表CRUD、基础查询、分页查询,这5个场景几乎能满足80%的日常开发需求,也是掌握SqlSugar的基础。
1. 核心基础:SqlSugar核心对象与初始化
SqlSugar的所有数据库操作,都围绕SqlSugarClient对象展开,它是SqlSugar的核心对象,负责管理数据库连接、执行SQL操作、处理实体映射等。初始化SqlSugarClient是使用SqlSugar的第一步,只需配置数据库连接字符串和数据库类型即可。
(1)核心对象说明
-
SqlSugarClient:核心客户端对象,所有数据库操作(CRUD、事务、查询等)都通过该对象执行,建议全局单例实例化(避免频繁创建和销毁连接,提升性能)。
-
ConnectionConfig:连接配置对象,用于配置数据库连接字符串、数据库类型、连接超时时间、是否开启日志等。
-
SugarTable/SugarColumn:可选的实体映射特性,用于自定义实体与数据库表的映射关系(如表名、字段名、主键、自增等),零配置场景下可省略。
(2)SqlSugarClient初始化(单例模式,推荐)
企业级开发中,建议使用单例模式实例化SqlSugarClient,避免频繁创建连接,提升系统性能。以下以SQL Server和MySQL为例,演示初始化方式:
csharp
using SqlSugar;
// 1. 全局单例 SqlSugarClient 实例(推荐)
public class SqlSugarHelper
{
// 私有构造函数,防止外部实例化
private SqlSugarHelper() { }
// 单例实例
private static readonly SqlSugarClient _instance;
// 静态构造函数,初始化 SqlSugarClient
static SqlSugarHelper()
{
// 配置连接信息(以SQL Server为例)
var config = new ConnectionConfig
{
ConnectionString = "Server=localhost;Database=SqlSugarDemo;Uid=sa;Pwd=123456;", // 连接字符串
DbType = DbType.SqlServer, // 数据库类型(SqlServer/MySql/Oracle等)
IsAutoCloseConnection = true, // 自动关闭连接(无需手动关闭,推荐开启)
InitKeyType = InitKeyType.Attribute, // 主键初始化方式(Attribute:通过特性配置,None:自动识别)
ConfigureExternalServices = new ConfigureExternalServices
{
// 可选:配置日志(如输出SQL语句,便于调试)
LogEvent = (sql, pars) =>
{
Console.WriteLine($"执行SQL:{sql}");
Console.WriteLine($"参数:{string.Join(",", pars.Select(p => $"{p.ParameterName}={p.Value}"))}");
}
}
};
// 初始化 SqlSugarClient
_instance = new SqlSugarClient(config);
// 可选:开启全局过滤(如软删除过滤,后续高级特性讲解)
// _instance.QueryFilter.Add(new TableFilterItem<BaseEntity>(it => it.IsDeleted == false));
}
// 提供全局访问入口
public static SqlSugarClient Instance => _instance;
}
// MySQL 连接配置示例(只需修改 ConnectionString 和 DbType)
var mysqlConfig = new ConnectionConfig
{
ConnectionString = "Server=localhost;Database=SqlSugarDemo;Uid=root;Pwd=123456;Port=3306;",
DbType = DbType.MySql,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute
};
关键配置说明:
-
IsAutoCloseConnection = true:开启自动关闭连接,无需手动调用Close()或使用using语句,SqlSugar会自动管理连接的开启与关闭,避免连接泄漏。 -
InitKeyType = InitKeyType.Attribute:通过特性(SugarTable、SugarColumn)配置实体与表的映射关系,若不使用特性,可设置为InitKeyType.None,SqlSugar会自动识别主键(默认识别名为"Id"的字段)。 -
LogEvent:配置日志输出,可将执行的SQL语句和参数输出到控制台、日志系统(如Serilog),便于开发调试。
2. 实体映射(零配置+自定义配置)
SqlSugar支持"零配置映射"和"自定义映射"两种方式,零配置场景下,实体类名与数据库表名一致、实体属性名与数据库字段名一致,无需任何配置;若表名、字段名与实体不一致,可通过SugarTable(类级特性)和SugarColumn(属性级特性)自定义映射。
(1)零配置映射(推荐,简单场景)
实体类名与数据库表名一致,属性名与字段名一致,主键字段名为"Id"(可自动识别为自增主键):
csharp
// 实体类(对应数据库中的 User 表)
public class User
{
// 主键(自动识别为自增主键,无需特性)
public int Id { get; set; }
// 对应数据库中的 UserName 字段
public string UserName { get; set; }
// 对应数据库中的 Email 字段
public string Email { get; set; }
// 对应数据库中的 Age 字段
public int Age { get; set; }
// 对应数据库中的 CreateTime 字段(DateTime类型)
public DateTime CreateTime { get; set; }
// 对应数据库中的 IsDeleted 字段(软删除标识)
public bool IsDeleted { get; set; }
}
说明:零配置映射适用于表名、字段名与实体一致的场景,无需任何额外配置,SqlSugar会自动完成映射,大幅提升开发效率。
(2)自定义映射(复杂场景)
当表名、字段名与实体不一致,或需要配置主键类型、自增、非空、默认值等属性时,使用SugarTable和SugarColumn特性:
csharp
using SqlSugar;
// SugarTable:自定义表名(实体类名 UserInfo,对应数据库表名 t_user)
[SugarTable("t_user")]
public class UserInfo
{
// SugarColumn:自定义字段名、主键、自增
[SugarColumn(ColumnName = "user_id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
// 自定义字段名(实体属性 UserName,对应数据库字段 user_name)
[SugarColumn(ColumnName = "user_name")]
public string UserName { get; set; }
// 非空约束
[SugarColumn(IsNullable = false)]
public string Email { get; set; }
// 默认值(数据库字段默认值为 18)
[SugarColumn(DefaultValue = "18")]
public int Age { get; set; }
// 忽略该属性(不映射到数据库表)
[SugarColumn(IsIgnore = true)]
public string Remark { get; set; }
// 日期类型,默认值为当前时间
[SugarColumn(DefaultValue = "GETDATE()", IsOnlyIgnoreInsert = false)]
public DateTime CreateTime { get; set; }
// 软删除标识(默认值为 false)
[SugarColumn(DefaultValue = "0")]
public bool IsDeleted { get; set; }
}
常用特性参数说明:
-
SugarTable(TableName):类级特性,指定实体对应的数据库表名。 -
ColumnName:属性级特性,指定属性对应的数据库字段名。 -
IsPrimaryKey:是否为主键,默认false。 -
IsIdentity:是否为自增主键,默认false(仅支持SQL Server、MySQL等支持自增的数据库)。 -
IsNullable:是否允许为空,默认true。 -
DefaultValue:数据库字段的默认值(如"18""GETDATE()")。 -
IsIgnore:是否忽略该属性,不映射到数据库表,默认false。 -
IsOnlyIgnoreInsert:插入操作时忽略该属性,更新时不忽略,默认false。
3. 单表CRUD操作(核心基础)
SqlSugar的单表CRUD操作采用链式API设计,语法简洁,一行代码即可完成,支持同步和异步两种方式(推荐异步,提升系统并发性能)。以下以User实体为例,演示单表CRUD的完整用法:
(1)新增操作(Insert)
csharp
using SqlSugar;
// 1. 新增单个实体(同步)
var user = new User
{
UserName = "张三",
Email = "zhangsan@example.com",
Age = 25,
CreateTime = DateTime.Now,
IsDeleted = false
};
// 执行新增,返回自增主键(若主键为自增)
int newId = SqlSugarHelper.Instance.Insertable(user).ExecuteReturnIdentity();
Console.WriteLine($"新增用户成功,用户ID:{newId}");
// 2. 新增单个实体(异步,推荐)
var userAsync = new User
{
UserName = "李四",
Email = "lisi@example.com",
Age = 28,
CreateTime = DateTime.Now,
IsDeleted = false
};
int newIdAsync = await SqlSugarHelper.Instance.Insertable(userAsync).ExecuteReturnIdentityAsync();
Console.WriteLine($"异步新增用户成功,用户ID:{newIdAsync}");
// 3. 批量新增(同步)
var userList = new List<User>
{
new User { UserName = "王五", Email = "wangwu@example.com", Age = 22, CreateTime = DateTime.Now, IsDeleted = false },
new User { UserName = "赵六", Email = "zhaoliu@example.com", Age = 30, CreateTime = DateTime.Now, IsDeleted = false }
};
// 执行批量新增,返回影响行数
int batchCount = SqlSugarHelper.Instance.Insertable(userList).ExecuteCommand();
Console.WriteLine($"批量新增用户成功,新增数量:{batchCount}");
// 4. 批量新增(异步,推荐)
int batchCountAsync = await SqlSugarHelper.Instance.Insertable(userList).ExecuteCommandAsync();
Console.WriteLine($"异步批量新增用户成功,新增数量:{batchCountAsync}");
关键说明:
-
Insertable(user):创建新增操作对象,参数为单个实体或实体列表。 -
ExecuteReturnIdentity():执行新增操作,并返回自增主键(仅当主键为自增时有效)。 -
ExecuteCommand():执行新增操作,返回影响的行数(批量新增时常用)。 -
异步方法后缀为
Async(如ExecuteReturnIdentityAsync),需配合await使用。
(2)查询操作(Query)
SqlSugar支持多种查询方式:根据主键查询、条件查询、分页查询、LINQ查询等,语法灵活,可按需选择。
csharp
using SqlSugar;
// 1. 根据主键查询(同步)
User userById = SqlSugarHelper.Instance.Queryable<User>().InSingle(1); // 根据ID=1查询
Console.WriteLine($"根据主键查询:{userById?.UserName}");
// 2. 根据主键查询(异步,推荐)
User userByIdAsync = await SqlSugarHelper.Instance.Queryable<User>().InSingleAsync(1);
// 3. 条件查询(链式API,推荐)
// 查询年龄大于25、未删除的用户,按创建时间降序排序,取前10条
var userList = SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.Age > 25 && u.IsDeleted == false) // 条件筛选
.OrderByDesc(u => u.CreateTime) // 降序排序
.Take(10) // 取前10条
.ToList(); // 转为列表
// 4. 条件查询(异步)
var userListAsync = await SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.UserName.Contains("张")) // 模糊查询(包含"张"字)
.OrderBy(u => u.Age) // 升序排序
.ToListAsync();
// 5. LINQ查询(熟悉LINQ的开发者首选)
var linqList = from u in SqlSugarHelper.Instance.Queryable<User>()
where u.Age >= 20 && u.IsDeleted == false
orderby u.CreateTime descending
select u;
List<User> linqResult = linqList.ToList();
// 6. 单值查询(获取符合条件的第一条数据)
User firstUser = SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.Email.EndsWith("@example.com"))
.First();
// 7. 统计查询(获取符合条件的用户数量)
int count = SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.IsDeleted == false)
.Count();
Console.WriteLine($"未删除用户总数:{count}");
// 8. 聚合查询(获取年龄最大值、最小值、平均值)
var aggregate = SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.IsDeleted == false)
.Select(u => new
{
MaxAge = SqlFunc.AggregateMax(u.Age), // 最大值
MinAge = SqlFunc.AggregateMin(u.Age), // 最小值
AvgAge = SqlFunc.AggregateAvg(u.Age) // 平均值
})
.First();
Console.WriteLine($"最大年龄:{aggregate.MaxAge},最小年龄:{aggregate.MinAge},平均年龄:{aggregate.AvgAge}");
关键说明:
-
Queryable<User>():创建查询操作对象,指定要查询的实体类型。 -
Where:添加查询条件,支持Lambda表达式,语法与LINQ一致。 -
OrderBy/OrderByDesc:排序,参数为排序字段。 -
Take/Skip:取前N条数据、跳过N条数据(分页常用)。 -
SqlFunc:SqlSugar提供的聚合函数工具类,支持Max、Min、Avg、Sum等聚合操作。
(3)更新操作(Update)
SqlSugar支持多种更新方式:全量更新、局部更新、条件更新、批量更新,避免不必要的字段更新,提升性能。
csharp
using SqlSugar;
// 1. 全量更新(根据主键更新,同步)
var userToUpdate = new User
{
Id = 1, // 主键,必须指定
UserName = "张三_更新",
Email = "zhangsan_update@example.com",
Age = 26,
CreateTime = DateTime.Now, // 会覆盖原有值
IsDeleted = false
};
// 执行全量更新,返回影响行数
int updateCount = SqlSugarHelper.Instance.Updateable(userToUpdate).ExecuteCommand();
Console.WriteLine($"全量更新成功,影响行数:{updateCount}");
// 2. 全量更新(异步,推荐)
int updateCountAsync = await SqlSugarHelper.Instance.Updateable(userToUpdate).ExecuteCommandAsync();
// 3. 局部更新(仅更新指定字段,推荐,提升性能)
// 方式1:指定字段更新
int partialUpdateCount = SqlSugarHelper.Instance.Updateable<User>()
.SetColumns(u => u.UserName == "张三_局部更新") // 要更新的字段
.SetColumns(u => u.Age == 27)
.Where(u => u.Id == 1) // 更新条件
.ExecuteCommand();
// 方式2:匿名对象更新(更简洁)
int partialUpdateCount2 = SqlSugarHelper.Instance.Updateable<User>()
.SetColumns(new { UserName = "张三_匿名更新", Age = 28 })
.Where(u => u.Id == 1)
.ExecuteCommand();
// 4. 批量更新(同步)
int batchUpdateCount = SqlSugarHelper.Instance.Updateable<User>()
.SetColumns(u => u.Age += 1) // 所有符合条件的用户年龄+1
.Where(u => u.Age < 30 && u.IsDeleted == false)
.ExecuteCommand();
Console.WriteLine($"批量更新成功,影响行数:{batchUpdateCount}");
// 5. 批量更新(异步,推荐)
int batchUpdateCountAsync = await SqlSugarHelper.Instance.Updateable<User>()
.SetColumns(u => u.IsDeleted == true)
.Where(u => u.CreateTime < DateTime.Now.AddMonths(-6)) // 半年前的用户标记为删除
.ExecuteCommandAsync();
关键说明:
-
全量更新需指定主键,且会更新实体的所有字段(包括未修改的字段),不推荐频繁使用。
-
局部更新通过
SetColumns指定要更新的字段,仅更新指定字段,提升性能,推荐使用。 -
批量更新通过
Where指定条件,一次性更新所有符合条件的记录,高效便捷。
(4)删除操作(Delete)
SqlSugar支持物理删除和逻辑删除(软删除),企业级开发中推荐使用软删除(标记IsDeleted字段,不真正删除数据),便于数据恢复和审计。
csharp
using SqlSugar;
// 1. 物理删除(根据主键删除,同步)
// 注意:物理删除会真正删除数据,谨慎使用
int deleteCount = SqlSugarHelper.Instance.Deleteable<User>().In(1).ExecuteCommand();
Console.WriteLine($"物理删除成功,影响行数:{deleteCount}");
// 2. 物理删除(异步,推荐)
int deleteCountAsync = await SqlSugarHelper.Instance.Deleteable<User>().In(1).ExecuteCommandAsync();
// 3. 条件物理删除
int deleteByConditionCount = SqlSugarHelper.Instance.Deleteable<User>()
.Where(u => u.Age > 50 && u.IsDeleted == false)
.ExecuteCommand();
// 4. 软删除(推荐,企业级常用)
// 本质是更新IsDeleted字段为true,不删除数据
int softDeleteCount = SqlSugarHelper.Instance.Updateable<User>()
.SetColumns(u => u.IsDeleted == true)
.Where(u => u.Id == 2)
.ExecuteCommand();
Console.WriteLine($"软删除成功,影响行数:{softDeleteCount}");
// 5. 批量软删除
int batchSoftDeleteCount = await SqlSugarHelper.Instance.Updateable<User>()
.SetColumns(u => u.IsDeleted == true)
.Where(u => u.CreateTime < DateTime.Now.AddYears(-1)) // 一年前的用户批量软删除
.ExecuteCommandAsync();
关键说明:
-
物理删除使用
Deleteable,会真正删除数据库中的数据,适合无需保留历史数据的场景。 -
软删除本质是更新操作,通过标记
IsDeleted字段实现,后续查询时通过过滤IsDeleted == false获取有效数据。 -
批量删除/软删除通过
Where指定条件,高效便捷,避免循环删除(提升性能)。
4. 分页查询(企业级常用)
分页查询是企业级开发中最常用的场景之一(如列表页分页),SqlSugar提供了简洁的分页API,支持同步和异步,自动生成高效的分页SQL,无需手动编写ROW_NUMBER()或LIMIT语句。
csharp
using SqlSugar;
// 分页参数
int pageIndex = 1; // 当前页码(从1开始)
int pageSize = 10; // 每页条数
int totalCount = 0; // 总记录数
int totalPage = 0; // 总页数
// 1. 基础分页(同步)
var pageList = SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.IsDeleted == false)
.OrderByDesc(u => u.CreateTime)
.ToPageList(pageIndex, pageSize, ref totalCount, ref totalPage);
Console.WriteLine($"当前页码:{pageIndex},每页条数:{pageSize},总记录数:{totalCount},总页数:{totalPage}");
// 2. 基础分页(异步,推荐)
var pageListAsync = await SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.IsDeleted == false && u.Age >= 20)
.OrderBy(u => u.Age)
.ToPageListAsync(pageIndex, pageSize, ref totalCount, ref totalPage);
// 3. 分页+条件筛选+排序(复杂场景)
var complexPageList = await SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.IsDeleted == false)
.WhereIF(!string.IsNullOrEmpty(keyword), u => u.UserName.Contains(keyword) || u.Email.Contains(keyword)) // 条件判断(关键字不为空时添加模糊查询)
.OrderByDesc(u => u.CreateTime)
.OrderBy(u => u.Age) // 多字段排序
.ToPageListAsync(pageIndex, pageSize, ref totalCount, ref totalPage);
// 4. 分页+聚合查询(获取分页数据的同时,统计相关信息)
var pageWithAggregate = await SqlSugarHelper.Instance.Queryable<User>()
.Where(u => u.IsDeleted == false)
.Select(u => new
{
u.Id,
u.UserName,
u.Email,
u.Age,
u.CreateTime
})
.ToPageListAsync(pageIndex, pageSize, ref totalCount, ref totalPage);
// 5. 自定义分页SQL(复杂场景,如多表联查分页)
var customPageList = await SqlSugarHelper.Instance.Ado.SqlQueryAsync<User>(
$"SELECT * FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY CreateTime DESC) AS RowNum FROM [User] WHERE IsDeleted = 0) AS T WHERE RowNum BETWEEN {(pageIndex-1)*pageSize + 1} AND {pageIndex*pageSize}");
// 手动查询总记录数
totalCount = await SqlSugarHelper.Instance.Ado.SqlQuerySingleAsync<int>("SELECT COUNT(*) FROM [User] WHERE IsDeleted = 0");
totalPage = (int)Math.Ceiling((double)totalCount / pageSize);
关键说明:
-
ToPageList(pageIndex, pageSize, ref totalCount, ref totalPage):核心分页方法,totalCount和totalPage为引用类型,会自动返回总记录数和总页数。 -
WhereIF(condition, expression):条件判断,当condition为true时,添加后续的查询条件,适用于动态筛选场景(如关键字查询)。 -
自定义分页SQL适用于多表联查等复杂场景,可手动编写分页SQL,灵活控制查询逻辑。
三、核心特性:SqlSugar高级用法(深度重点)
基础用法能满足日常开发需求,而SqlSugar的高级特性则能适配复杂企业级场景(如多表联查、事务管理、动态SQL、分表分库、缓存、数据库迁移),这也是它区别于其他ORM的核心优势,更是企业级开发必备的技能。
1. 多表联查(企业级高频场景)
实际开发中,很少存在单表操作,多表联查(内连接、左连接、右连接、全连接)是高频场景,SqlSugar支持链式API和LINQ两种方式实现多表联查,语法简洁,自动生成高效的联查SQL。
首先定义关联实体(以用户、角色、用户角色关联表为例):
csharp
// 用户表(User)
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public int Age { get; set; }
public DateTime CreateTime { get; set; }
public bool IsDeleted { get; set; }
}
// 角色表(Role)
public class Role
{
public int Id { get; set; }
public string RoleName { get; set; } // 角色名称(如管理员、普通用户)
public string Description { get; set; } // 角色描述
public bool IsDeleted { get; set; }
}
// 用户角色关联表(UserRole,多对多关联)
public class UserRole
{
public int Id { get; set; }
public int UserId { get; set; } // 关联用户ID
public int RoleId { get; set; } // 关联角色ID
public bool IsDeleted { get; set; }
}
(1)内连接(Inner Join)
查询同时存在于两个表中的数据(如查询用户及其关联的角色信息):
csharp
using SqlSugar;
// 方式1:链式API(推荐,简洁直观)
var innerJoinList = await SqlSugarHelper.Instance.Queryable<User, UserRole, Role>((u, ur, r) => new JoinQueryInfos(
JoinType.Inner, u.Id == ur.UserId, // User与UserRole内连接,条件:UserId匹配
JoinType.Inner, ur.RoleId == r.Id // UserRole与Role内连接,条件:RoleId匹配
))
.Where((u, ur, r) => u.IsDeleted == false && r.IsDeleted == false)
.Select((u, ur, r) => new
{
UserId = u.Id,
UserName = u.UserName,
Email = u.Email,
RoleId = r.Id,
RoleName = r.RoleName
})
.ToListAsync();
// 方式2:LINQ方式
var linqInnerJoin = from u in SqlSugarHelper.Instance.Queryable<User>()
join ur in SqlSugarHelper.Instance.Queryable<UserRole>() on u.Id equals ur.UserId
join r in SqlSugarHelper.Instance.Queryable<Role>() on ur.RoleId equals r.Id
where u.IsDeleted == false && r.IsDeleted == false
select new
{
UserId = u.Id,
UserName = u.UserName,
RoleName = r.RoleName
};
var linqInnerJoinResult = await linqInnerJoin.ToListAsync();
(2)左连接(Left Join)
查询左表所有数据,右表匹配的数据显示,不匹配的显示为null(如查询所有用户,以及其关联的角色,无角色的用户也显示):
csharp
// 链式API实现左连接
var leftJoinList = await SqlSugarHelper.Instance.Queryable<User, UserRole, Role>((u, ur, r) => new JoinQueryInfos(
JoinType.Left, u.Id == ur.UserId, // User与UserRole左连接
JoinType.Left, ur.RoleId == r.Id // UserRole与Role左连接
))
.Where(u => u.IsDeleted == false)
.Select((u, ur, r) => new
{
UserId = u.Id,
UserName = u.UserName,
RoleName = r?.RoleName ?? "无角色" // 右表无匹配时显示"无角色"
})
.ToListAsync();
(3)右连接(Right Join)
与左连接相反,查询右表所有数据,左表匹配的数据显示,不匹配的显示为null(如查询所有角色,以及关联的用户,无用户的角色也显示):
csharp
var rightJoinList = await SqlSugarHelper.Instance.Queryable<User, UserRole, Role>((u, ur, r) => new JoinQueryInfos(
JoinType.Right, u.Id == ur.UserId, // User与UserRole右连接
JoinType.Right, ur.RoleId == r.Id // UserRole与Role右连接