C#常用类库-详解SqlSugar

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)自定义映射(复杂场景)

当表名、字段名与实体不一致,或需要配置主键类型、自增、非空、默认值等属性时,使用SugarTableSugarColumn特性:

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):核心分页方法,totalCounttotalPage为引用类型,会自动返回总记录数和总页数。

  • 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右连接
相关推荐
似水明俊德2 小时前
06-C#
开发语言·c++·算法·c#
云栖梦泽2 小时前
易语言开发从入门到精通:进阶篇·图形图像高级实战
开发语言
m0_662577972 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
程序员小李白2 小时前
vue2基本语法详细解析(2.7条件渲染)
开发语言·前端·javascript
档案宝档案管理2 小时前
档案宝|开箱即用,打破档案管理“复杂魔咒”
数据库·人工智能·档案·档案管理
xyq20242 小时前
Chart.js 安装指南
开发语言
Predestination王瀞潞2 小时前
1. Java SE到底是什么:不仅仅是面向对象
java·开发语言
Byron07072 小时前
Python面向对象编程(OOP)详解:类、对象、继承、多态、封装
开发语言·python
小朋友,你是否有很多问号?2 小时前
java udf 实现经纬度匹配pg数据库public.geometry地理位置
数据库