简介
在构建 SaaS 平台、中台系统或需要频繁动态扩展业务实体的项目中,传统的静态编译实体映射已无法满足需求。SqlSugar 作为国产优秀的 ORM 框架,凭借其强大的 DynamicBuilder(动态构建)和 Multi-Tenancy(多租户/多库)支持,成为了此类场景下的首选方案。
本文将深入探讨如何利用 SqlSugar 在运行时动态创建表、维护多库环境、实现跨库联表查询,以及应用全局过滤器保障数据安全。
1. 动态建模与 CodeFirst 演进
SqlSugar 的 CodeFirst 能够根据 C# 类自动同步数据库表结构。除了基础的特性建模,它还支持完全脱离物理类的“动态建模”。
1.1 场景一:基于特性的标准建模
这是最常用的方式,适合业务相对固定的模块。通过特性定义字段元数据,确保跨数据库(MySQL/SQLServer/Oracle)的行为一致。
[SugarTable("Base_User")]public class UserEntity{ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; }
[SugarColumn(ColumnDescription = "用户名", Length = 50)] public string Name { get; set; }
[SugarColumn(IsNullable = true, DefaultValue = "getdate()")] public DateTime CreateTime { get; set; }}
// 一键同步/创建表db.CodeFirst.InitTables(typeof(UserEntity));1.2 场景二:运行时动态创建类 (DynamicBuilder)
应用场景:用户自定义表单、低代码平台。你不需要预先写好 .cs 文件,可以在程序运行时根据配置文件生成表。
var dynamicType = db.DynamicBuilder() .CreateClass("Custom_Report_001", new SugarTable()) .CreateProperty("Id", typeof(int), new SugarColumn() { IsPrimaryKey = true, IsIdentity = true }) .CreateProperty("ExtData", typeof(string), new SugarColumn() { Length = 1000 }) .BuilderType(); // 此时在内存中生成了一个 Type
db.CodeFirst.InitTables(dynamicType); // 物理表同步生成2. 强大的数据库维护 (DbMaintenance)
SqlSugar 封装了 DbMaintenance 接口,将各数据库底层复杂的系统表查询抽象为简单的 API,非常适合做数据库管理工具或自动化迁移。
- 元数据检索:
db.DbMaintenance.GetTableInfoList()获取所有表结构。 - 结构变更:
db.DbMaintenance.AddColumn("TableName", new DbColumnInfo(){...})动态加字段。 - 安全运维:
db.DbMaintenance.BackupDataBase("dbName", "path")快速备份。
3. 多租户与跨库联表查询
在大型系统中,数据往往散落在不同的服务器或数据库实例中。SqlSugar 提供了“天生”的跨库支持。
3.1 自动路由跨库 (TenantAttribute)
通过 ConfigId 标识不同的数据库,并利用特性绑定实体与库的关系。
// 库A的配置 ID 为 "Sales"[Tenant("Sales")]public class Order { ... }
// 库B的配置 ID 为 "Finance"[Tenant("Finance")]public class Invoice { ... }
// 执行时,SqlSugar 会自动切换连接var list = db.Queryable<Order>() .LeftJoin<Invoice>((o, i) => o.Id == i.OrderId) .ToList();3.2 灵活的手动联表
如果库名是动态的(如按年分库),可以使用 .As() 语法:
var query = db.Queryable<Order>().As("Database_2023.dbo.Orders") .LeftJoin<Customer>((o, c) => o.CustomerId == c.Id, "Database_Shared.dbo.Customers") .ToList();4. 数据安全隔离:全局过滤器 (QueryFilter)
在多租户系统或逻辑删除需求中,手动在每个 Where 里写 IsDeleted == false 既低效又易出错。
// 配置全局过滤器db.QueryFilter.AddTableFilter<IDeletedFilter>(it => it.IsDeleted == false);
// 此时所有的查询(包括联表查询)都会自动带上 IsDeleted = 0 的条件var data = db.Queryable<UserEntity>().ToList();5. 动态 CRUD 操作实战
对于动态创建的类,由于没有泛型类型,我们使用 ByObject 系列方法:
// 1. 根据动态类型创建对象var obj = db.DynamicBuilder().CreateObjectByType(dynamicType, new Dictionary<string, object>() { { "ExtData", "这是一条动态插入的数据" }});
// 2. 插入数据db.InsertableByObject(obj).ExecuteCommand();
// 3. 动态查询var list = db.Queryable(dynamicType).Where("Id = @id", new { id = 1 }).ToList();结论
SqlSugar 不仅仅是一个 ORM,它更像是一个数据库操作框架。通过 CodeFirst 解决了结构一致性问题,通过 DynamicBuilder 解决了灵活性问题,而 多租户与过滤器 则解决了复杂的架构维护问题。
在当今微服务和低代码风靡的背景下,掌握这些动态操作技巧,能让你的系统架构具备极高的弹性。