ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SqlSugar ORM框架:高效数据更新操作指南

SqlSugar ORM框架:高效数据更新操作指南 1. SqlSugar ORM框架概述SqlSugar是一款老牌.NET开源ORM框架由果糖大数据科技团队维护和更新。作为.NET生态中最易上手的ORM工具之一它凭借开箱即用的特性和丰富的功能集在开发者社区中积累了良好的口碑。经过10年的持续迭代SqlSugar已经发展成为一个功能全面、性能优异且支持多数据库的成熟ORM解决方案。提示ORM对象关系映射的核心价值在于让开发者能够用面向对象的方式操作数据库避免直接编写繁琐的SQL语句。与Entity Framework等ORM工具相比SqlSugar具有以下几个显著特点学习曲线平缓入门门槛低原生支持多种数据库切换成本极小提供了完善的CRUD操作API性能优化到位特别适合大数据量场景拥有活跃的社区支持和及时的更新维护在实际项目中SqlSugar特别适合以下场景需要快速开发的数据驱动型应用多数据库支持的项目对性能有较高要求的系统需要处理大量数据的业务场景2. 环境准备与基础配置2.1 安装SqlSugar在.NET项目中安装SqlSugar非常简单可以通过NuGet包管理器直接安装Install-Package SqlSugar或者使用.NET CLIdotnet add package SqlSugar2.2 基本配置配置SqlSugar连接数据库通常需要以下几个步骤// 创建SqlSugarScope实例推荐单例模式 var sqlSugar new SqlSugarScope(new ConnectionConfig() { ConnectionString Server.;DatabaseTestDB;Uidsa;Pwd123456;, // 连接字符串 DbType DbType.SqlServer, // 数据库类型 IsAutoCloseConnection true // 自动释放 }, db { // 这里可以配置AOP等 });注意SqlSugarScope是线程安全的建议在应用程序生命周期内保持单例。2.3 实体类定义SqlSugar支持标准的POCO类作为实体以下是一个典型的实体类定义[SugarTable(Student)] // 指定表名 public class Student { [SugarColumn(IsPrimaryKey true, IsIdentity true)] // 主键且自增 public int Id { get; set; } [SugarColumn(Length 50)] // 字段长度 public string Name { get; set; } public int Age { get; set; } [SugarColumn(IsNullable true)] // 允许为空 public string Address { get; set; } [SugarColumn(IsIgnore true)] // 忽略此属性不映射到数据库 public string TempInfo { get; set; } }3. SqlSugar更新数据语法详解3.1 基础更新操作3.1.1 根据主键更新这是最简单的更新方式SqlSugar会自动识别实体类的主键var student new Student { Id 1, Name 更新后的名字, Age 20 }; // 根据主键更新 var result sqlSugar.Updateable(student).ExecuteCommand();3.1.2 条件更新当需要根据非主键字段进行更新时可以使用Where条件// 更新所有年龄大于18的学生名字 sqlSugar.UpdateableStudent() .SetColumns(it new Student() { Name 成年人 }) .Where(it it.Age 18) .ExecuteCommand();3.1.3 更新指定列如果只需要更新部分字段可以使用SetColumns方法// 只更新Name字段 sqlSugar.UpdateableStudent() .SetColumns(it it.Name 新名字) .Where(it it.Id 1) .ExecuteCommand();3.2 高级更新技巧3.2.1 批量更新SqlSugar提供了高效的批量更新方式var updateList new ListStudent { new Student { Id 1, Name 张三 }, new Student { Id 2, Name 李四 } }; // 批量更新 sqlSugar.Updateable(updateList).ExecuteCommand();对于大量数据的批量更新建议使用分批处理// 每1000条一批进行更新 sqlSugar.Updateable(updateList).ExecuteCommand(1000);3.2.2 表达式更新SqlSugar支持丰富的表达式更新语法// 使用表达式进行字段运算 sqlSugar.UpdateableStudent() .SetColumns(it it.Age it.Age 1) // 年龄加1 .Where(it it.Id 1) .ExecuteCommand();3.2.3 联表更新SqlSugar支持复杂的联表更新操作sqlSugar.UpdateableStudent() .SetColumns(it new Student { Name 联表更新 }) .Where(it it.Id sqlSugar.QueryableClass() .Where(c c.ClassName 一班) .Select(c c.ClassId) .First()) .ExecuteCommand();3.3 无实体更新SqlSugar支持不依赖实体类的更新操作这在动态场景中非常有用// 使用字典进行无实体更新 sqlSugar.Updateableobject() .AS(Student) // 指定表名 .SetColumns(new Dictionarystring, object { { Name, 无实体更新 } }) .Where(Id id, new { id 1 }) .ExecuteCommand();或者使用SQL字符串sqlSugar.Ado.ExecuteCommand(UPDATE Student SET Name name WHERE Id id, new { name SQL更新, id 1 });4. 更新操作的最佳实践与性能优化4.1 事务处理更新操作通常需要事务支持SqlSugar提供了多种事务管理方式// 方式1使用事务范围 try { sqlSugar.BeginTran(); // 执行多个更新操作 sqlSugar.UpdateableStudent(...).ExecuteCommand(); sqlSugar.UpdateableClass(...).ExecuteCommand(); sqlSugar.CommitTran(); } catch { sqlSugar.RollbackTran(); throw; } // 方式2使用仓储模式的事务 var result sqlSugar.UseTran(() { // 事务内的操作 sqlSugar.UpdateableStudent(...).ExecuteCommand(); sqlSugar.UpdateableClass(...).ExecuteCommand(); }); if (!result.IsSuccess) { // 处理失败情况 }4.2 并发控制对于可能产生并发冲突的更新操作SqlSugar提供了乐观锁支持// 在实体类中添加版本控制字段 [SugarTable(Product)] public class Product { [SugarColumn(IsPrimaryKey true)] public int Id { get; set; } public string Name { get; set; } [SugarColumn(IsVersion true)] // 乐观锁字段 public int Version { get; set; } } // 更新时会自动检查版本 var result sqlSugar.Updateable(product).ExecuteCommand(); if (result 0) { // 更新失败数据已被修改 }4.3 性能优化建议批量操作对于大量数据更新始终使用批量操作而非循环单条更新字段精确只更新必要的字段避免使用Updateable(entity)更新所有字段索引利用确保WHERE条件中的字段有适当索引连接管理合理配置连接池大小默认100异步操作高并发场景考虑使用异步API// 异步更新示例 await sqlSugar.Updateable(student).ExecuteCommandAsync();4.4 监控与日志SqlSugar提供了AOP支持可以方便地监控更新操作var sqlSugar new SqlSugarScope(new ConnectionConfig() { // 配置... }, db { db.Aop.OnLogExecuting (sql, pars) { Console.WriteLine(sql); // 输出执行的SQL }; db.Aop.OnError (exp) { // 处理错误 }; });5. 实际应用场景解析5.1 电商系统中的库存更新在电商系统中库存更新是一个典型的高并发更新场景// 使用乐观锁减少库存 public bool ReduceInventory(int productId, int quantity) { return sqlSugar.UseTran(() { var product sqlSugar.QueryableProduct() .Where(p p.Id productId) .First(); if (product.Stock quantity) throw new Exception(库存不足); product.Stock - quantity; return sqlSugar.Updateable(product).ExecuteCommand() 0; }).IsSuccess; }5.2 用户信息的多表更新用户信息通常分散在多个表中需要事务保证一致性public bool UpdateUserInfo(User user, UserDetail detail) { return sqlSugar.UseTran(() { sqlSugar.Updateable(user).ExecuteCommand(); sqlSugar.Updateable(detail).ExecuteCommand(); }).IsSuccess; }5.3 定时任务中的批量更新对于后台定时任务中的批量数据处理public void BatchUpdateUserStatus() { // 每次处理1000条 var pageIndex 1; var pageSize 1000; int total; do { var list sqlSugar.QueryableUser() .Where(u u.LastLoginTime DateTime.Now.AddMonths(-6)) .ToPageList(pageIndex, pageSize, ref total); sqlSugar.UpdateableUser() .SetColumns(u new User { Status Inactive }) .Where(u list.Select(x x.Id).Contains(u.Id)) .ExecuteCommand(); pageIndex; } while (pageIndex * pageSize total); }5.4 动态字段更新对于需要根据条件动态决定更新字段的场景public void DynamicUpdate(int id, Dictionarystring, object fields) { var update sqlSugar.UpdateableStudent(); foreach (var field in fields) { update.SetColumnsIF(true, field.Key field.Key, field.Value); } update.Where(it it.Id id).ExecuteCommand(); }6. 常见问题与解决方案6.1 更新不生效的排查步骤检查连接字符串是否正确确认实体类主键配置正确检查WHERE条件是否匹配到数据查看SQL日志确认生成的SQL语句检查是否有事务未提交6.2 性能问题分析如果遇到更新性能问题可以从以下几个方面排查数据库索引是否合理是否更新了不必要的字段批量操作的数据量是否过大是否有锁竞争情况6.3 特殊数据类型处理处理特殊数据类型时需要特别注意// JSON类型处理 [SugarColumn(ColumnDataType nvarchar(max), IsJson true)] public Dictionarystring, object ExtendedInfo { get; set; } // 枚举类型处理 public enum UserType { Admin, User, Guest } [SugarColumn(ColumnDataType int)] public UserType Type { get; set; }6.4 跨数据库兼容性SqlSugar虽然支持多数据库但某些语法在不同数据库中可能有差异// 使用SqlFunc类保证跨数据库兼容性 sqlSugar.UpdateableStudent() .SetColumns(it it.Name SqlFunc.MergeString(it.Name, _new)) .Where(it it.Id 1) .ExecuteCommand();7. 扩展知识与进阶技巧7.1 使用仓储模式组织更新代码对于大型项目建议使用仓储模式组织数据访问代码public class StudentRepository { private readonly ISqlSugarClient _db; public StudentRepository(ISqlSugarClient db) { _db db; } public int UpdateName(int id, string newName) { return _db.UpdateableStudent() .SetColumns(it it.Name newName) .Where(it it.Id id) .ExecuteCommand(); } // 其他更新方法... }7.2 结合Dapper实现特殊需求对于SqlSugar不支持的极端性能需求可以结合Dapperpublic void HybridUpdate() { using (var conn sqlSugar.Ado.Connection) { var dapper new DapperWrapper(conn); dapper.Execute(UPDATE Student SET Name Name WHERE Id Id, new { Name Dapper更新, Id 1 }); } }7.3 自定义扩展方法可以针对常用更新模式创建扩展方法public static class SqlSugarExtensions { public static int UpdateStatusT(this ISqlSugarClient db, int id, string status) where T : class, new() { return db.UpdateableT() .SetColumns(it (it as dynamic).Status status) .Where(it (it as dynamic).Id id) .ExecuteCommand(); } } // 使用示例 sqlSugar.UpdateStatusStudent(1, Active);7.4 使用ValueObject进行复杂更新对于值对象模式的更新public class Student { public int Id { get; set; } [SugarColumn(IsOwnsOne true)] // 值对象 public Address HomeAddress { get; set; } } public class Address { public string City { get; set; } public string Street { get; set; } } // 更新值对象 sqlSugar.UpdateableStudent() .SetColumns(it it.HomeAddress.City 北京) .Where(it it.Id 1) .ExecuteCommand();在实际项目中使用SqlSugar进行数据更新操作时我发现合理组织更新代码可以显著提高维护性。对于复杂的业务逻辑将更新操作封装在领域服务中而不是直接在控制器或API中调用SqlSugar能够更好地管理业务规则和数据一致性。另外对于高频更新的字段考虑添加适当的数据库索引可以大幅提升性能但同时也要注意索引对写入性能的影响。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进