C# 数据访问:SqlSugar vs Dapper 深度对比
C# 数据访问:SqlSugar vs Dapper 深度对比
根本差异:SqlSugar 是全功能 ORM(用代码代替 SQL),Dapper 是微型 ORM(SQL 驱动开发)。
性能方面
- 批量操作:SqlSugar 碾压级领先,批量插入快约 8 倍(使用了
SqlBulkCopy等原生 API) - 普通 CRUD:两者基本持平,差距在 5%~10% 内
- 简单查询:Dapper 略快,更接近原生 ADO.NET
功能方面
- SqlSugar 内建分表分库、多租户、读写分离、Code First、导航属性等企业级特性
- Dapper 极度轻量,只做参数绑定和结果映射,高级功能全部需要手写或扩展库
生态方面
- Dapper 全球影响力更大(18.3k Stars / 2 亿+ NuGet 下载)
- SqlSugar 中文社区更活跃,国产数据库支持全面(达梦、人大金仓、OceanBase 等)
选型一句话
- 追求开发效率 → SqlSugar
- 追求极致性能 + SQL 可控 → Dapper
- 两者可混合使用,各取所长
一、框架概览
| 维度 | SqlSugar | Dapper |
|---|---|---|
| 定位 | 全功能轻量级 ORM | 微型 ORM(Micro ORM) |
| 作者 | 果糖大数据团队(国内) | Stack Overflow 团队 |
| 首次发布 | 2014 年 | 2011 年 |
| GitHub Stars | ~5.8k | ~18.3k |
| NuGet 总下载量 | ~1000 万+ | ~2 亿+(生态更广) |
| 最新版本 | 5.1.4.x | 2.1.79 |
| 目标框架 | .NET Standard 2.0+ / .NET Framework 4.5+ | .NET Standard 2.0+ / .NET Framework 4.6.1+ |
| 开源协议 | MIT | Apache-2.0 |
二、核心理念差异
SqlSugar:用代码代替 SQL —— 通过链式 API 和 Lambda 表达式,让开发者尽量少写甚至不写 SQL。
Dapper:用 SQL 驱动开发 —— 开发者手写 SQL,框架只负责参数绑定和结果映射。
这是一个根本性的取舍:
- 选择 SqlSugar,意味着用开发效率换 SQL 控制力
- 选择 Dapper,意味着用 SQL 控制力换开发效率
三、功能特性对比
3.1 基础 CRUD
| 特性 | SqlSugar | Dapper |
|---|---|---|
| 查询单条 | ✅ db.Queryable<T>().First() |
✅ conn.QueryFirst<T>(sql) |
| 查询列表 | ✅ db.Queryable<T>().ToList() |
✅ conn.Query<T>(sql) |
| 插入 | ✅ db.Insertable(obj).ExecuteCommand() |
✅ conn.Execute(sql, obj) |
| 更新 | ✅ db.Updateable(obj).ExecuteCommand() |
✅ conn.Execute(sql, obj) |
| 删除 | ✅ db.Deleteable(obj).ExecuteCommand() |
✅ conn.Execute(sql, obj) |
| 是否需要手写 SQL | ❌ 自动生成 | ✅ 必须手写 |
3.2 高级查询能力
| 特性 | SqlSugar | Dapper |
|---|---|---|
| Lambda 表达式查询 | ✅ 原生支持 | ❌ 不支持 |
| 链式 API | ✅ .Where().OrderBy().Select() |
❌ 无 |
| 多表 JOIN | ✅ .LeftJoin<T2>() |
⚠️ 手写 SQL + 多映射 |
| 子查询 | ✅ 内建支持 | ⚠️ 手写 SQL |
| 动态条件拼接 | ✅ .WhereIF(cond, expr) |
⚠️ 需拼接 SQL 字符串 |
| 分页查询 | ✅ .ToPageList(pageNum, pageSize) |
⚠️ 手写 OFFSET/FETCH |
| 分组聚合 | ✅ .GroupBy().Having() |
⚠️ 手写 GROUP BY |
| 联表查询映射 | ✅ 导航属性自动映射 | ⚠️ splitOn 手动指定 |
3.3 批量操作
| 特性 | SqlSugar | Dapper |
|---|---|---|
| 批量插入 | ✅ Fastest<T>().BulkCopy() |
⚠️ 逐条执行或扩展库 |
| 批量更新 | ✅ 内建优化 | ⚠️ 逐条执行 |
| 批量删除 | ✅ .In(idList) |
⚠️ 手写 IN 语句 |
📌 SqlSugar 在批量操作中使用了
SqlBulkCopy等数据库原生批量 API,性能远超 Dapper 的逐条执行方式。
3.4 数据库支持
| 数据库 | SqlSugar | Dapper |
|---|---|---|
| SQL Server | ✅ | ✅ |
| MySQL | ✅ | ✅ |
| PostgreSQL | ✅ | ✅ |
| Oracle | ✅ | ✅ |
| SQLite | ✅ | ✅ |
| 达梦(DM) | ✅ | ⚠️ 需适配 |
| 人大金仓 | ✅ | ⚠️ 需适配 |
| 神通(Oscar) | ✅ | ⚠️ 需适配 |
| OceanBase | ✅ | ⚠️ 需适配 |
| 华为 GaussDB | ✅ | ⚠️ 需适配 |
📌 SqlSugar 对国产数据库的支持远优于 Dapper,这是国内项目选型的重要考量因素。
3.5 其他实用特性
| 特性 | SqlSugar | Dapper |
|---|---|---|
| Code First | ✅ 自动建表/迁移 | ❌ |
| Db First | ✅ 从数据库生成实体 | ❌ |
| 多租户 | ✅ 内建支持 | ❌ 需自行实现 |
| 读写分离 | ✅ 内建支持 | ❌ 需自行实现 |
| 分表分库 | ✅ 内建支持 | ❌ 需自行实现 |
| 全局过滤器 | ✅ .QueryFilter |
❌ |
| 逻辑删除 | ✅ .IsDeleted |
❌ 需自行实现 |
| 种子数据 | ✅ | ❌ |
| AOP / SQL 审计 | ✅ | ❌ 需自行封装 |
| 二级缓存 | ✅ 内建 | ❌ |
| JSON 列映射 | ✅ | ⚠️ 需手动处理 |
| 树形结构查询 | ✅ .ToTree() |
❌ |
| 模型验证 | ✅ | ❌ |
| 值对象映射 | ✅ | ⚠️ 需自定义 TypeHandler |
四、性能基准对比
基于标准测试(Release 模式,每轮 10 次取均值):
4.1 8 场性能对决
| 场次 | 测试项目 | SqlSugar | Dapper | 胜方 |
|---|---|---|---|---|
| 1 | 查询所有(100 万条,实体转换) | 100 | 95 | SqlSugar 小胜 |
| 2 | 查询单条(执行 1000 次) | 100 | 100 | 平手 |
| 3 | 批量更新(1000 条) | 100 | 60 | SqlSugar 大胜 |
| 4 | 批量插入(1000 条) | 100 | 12 | SqlSugar 碾压 |
| 5 | 批量删除(1000 条) | 100 | 50 | SqlSugar 大胜 |
| 6 | 分页查询(3000 次) | 96 | 100 | Dapper 小胜 |
| 7 | 普通插入(1000 次) | 100 | 96 | SqlSugar 小胜 |
| 8 | 普通更新(单条) | 90 | 100 | Dapper 小胜 |
4.2 性能结论
| 操作类型 | 结论 |
|---|---|
| 批量操作 | SqlSugar 碾压级优势,批量插入领先约 8 倍,批量更新领先约 1.7 倍 |
| 普通 CRUD | 两者基本持平,差距在 5%~10% 以内 |
| 简单查询 | Dapper 略快,更接近原生 ADO.NET |
原因分析:SqlSugar 批量操作使用了
SqlBulkCopy/SqlBulkReplace等数据库原生批量 API;Dapper 的批量操作本质上是逐条生成 SQL 执行,未做底层批量优化。
五、代码风格对比
5.1 查询示例
SqlSugar(链式 API + Lambda):
// 多条件分页查询
var users = db.Queryable<User>()
.Where(u => u.Age > 18 && u.Status == "Active")
.WhereIF(!string.IsNullOrEmpty(keyword), u => u.Name.Contains(keyword))
.OrderBy(u => u.CreateTime, OrderByType.Desc)
.Select(u => new { u.Id, u.Name, u.Age })
.ToPageList(pageNum, pageSize, ref totalCount);
Dapper(手写 SQL):
// 多条件分页查询
var sql = @"
SELECT Id, Name, Age, COUNT(*) OVER() AS TotalCount
FROM Users
WHERE Age > @Age AND Status = @Status";
if (!string.IsNullOrEmpty(keyword))
sql += " AND Name LIKE '%' + @Keyword + '%'";
sql += " ORDER BY CreateTime DESC OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY";
var users = conn.Query<UserDto>(sql, new { Age = 18, Status = "Active", Keyword = keyword, Offset = (pageNum - 1) * pageSize, PageSize = pageSize });
5.2 插入示例
SqlSugar:
db.Insertable(new User { Name = "张三", Age = 25 }).ExecuteCommand();
// 批量插入
db.Insertable(userList).ExecuteCommand();
// 或使用 Fastest 高性能插入
db.Fastest<User>().BulkCopy(userList);
Dapper:
conn.Execute("INSERT INTO Users (Name, Age) VALUES (@Name, @Age)",
new { Name = "张三", Age = 25 });
// 批量插入(需 Dapper.Contrib 扩展)
conn.Execute("INSERT INTO Users (Name, Age) VALUES (@Name, @Age)", userList);
5.3 多表关联示例
SqlSugar:
var list = db.Queryable<Order>()
.LeftJoin<OrderItem>((o, i) => o.Id == i.OrderId)
.LeftJoin<User>((o, i, u) => o.UserId == u.Id)
.Where((o, i, u) => u.Status == "Active")
.Select((o, i, u) => new OrderVo {
OrderId = o.Id,
UserName = u.Name,
ItemName = i.Name
})
.ToList();
Dapper:
var sql = @"
SELECT o.Id AS OrderId, u.Name AS UserName, i.Name AS ItemName
FROM Orders o
LEFT JOIN OrderItems i ON o.Id = i.OrderId
LEFT JOIN Users u ON o.UserId = u.Id
WHERE u.Status = @Status";
var list = conn.Query<OrderVo, UserVo, OrderItemVo, OrderVo>(
sql,
(order, user, item) => { order.UserName = user.Name; order.ItemName = item.Name; return order; },
new { Status = "Active" },
splitOn: "UserName,ItemName"
);
六、生态与社区
| 维度 | SqlSugar | Dapper |
|---|---|---|
| GitHub Stars | ~5.8k | ~18.3k |
| NuGet 总下载 | ~1000 万+ | ~2 亿+ |
| Stack Overflow 问答 | 较少 | 大量 |
| 中文社区 | 非常活跃(中文文档完善) | 一般 |
| 英文文档 | 有但不够完善 | 完善 |
| 更新频率 | 高(几乎每周更新) | 低(稳定,较少更新) |
| 配套扩展 | 内建大部分功能 | 需 Dapper.Contrib / Dapper.Rainbow 等 |
| 企业背书 | 国内大量企业采用 | Stack Overflow 生产使用 |
七、优缺点总结
SqlSugar
| ✅ 优势 | ❌ 劣势 |
|---|---|
| 开发效率极高,链式 API 上手快 | 社区规模和国际化不及 Dapper |
| 批量操作性能碾压级领先 | 隐藏 SQL 细节,调试复杂查询较难 |
| 国产数据库支持全面 | 框架较重,功能耦合度高 |
| 内建分表分库、多租户、读写分离 | 文档质量参差不齐 |
| 中文文档和社区活跃 | 非微软官方,长期维护有风险 |
| Code First / Db First 双模式 | 复杂场景下生成的 SQL 可能非最优 |
| 持续高频更新 | 版本迭代快,偶尔有 breaking change |
Dapper
| ✅ 优势 | ❌ 劣势 |
|---|---|
| 极致性能,接近原生 ADO.NET | 需要手写大量 SQL |
| 极轻量,单个文件即可集成 | 无自动映射,复杂对象需手动处理 |
| SQL 完全可控可调优 | 批量操作性能差 |
| Stack Overflow 生产验证,稳定可靠 | 缺少高级 ORM 特性 |
| 社区庞大,资料丰富 | 项目变大后 SQL 维护成本高 |
| 学习成本极低(对 SQL 熟练者) | 无 Code First / 迁移能力 |
| 扩展生态(Contrib / Rainbow 等) | 无内建分页、分表、多租户等企业级功能 |
八、选型建议
8.1 场景推荐
| 你的场景 | 推荐 | 理由 |
|---|---|---|
| 中小型项目快速交付 | SqlSugar | 链式 API + 内建功能,开发效率高 |
| 需要支持国产数据库 | SqlSugar | 原生支持达梦、人大金仓等 |
| 高并发 / 性能敏感系统 | Dapper | 接近原生 SQL 的极致性能 |
| 需要精细调优 SQL | Dapper | SQL 完全可控 |
| 大量批量导入/导出 | SqlSugar | BulkCopy 级批量操作 |
| 分表分库架构 | SqlSugar | 内建支持 |
| 团队 SQL 经验丰富 | Dapper | 发挥手写 SQL 优势 |
| 团队偏好代码优先 | SqlSugar | Lambda + 链式 API |
| 微服务轻量数据访问层 | Dapper | 轻量无依赖 |
| 企业后台管理系统 | SqlSugar | 快速 CRUD + 内建分页 |
| 国际化项目 | Dapper | 全球社区和英文文档更完善 |
8.2 决策流程图
开始选型
│
├─ 是否需要国产数据库支持?
│ └─ 是 → SqlSugar
│
├─ 是否需要分表分库 / 多租户?
│ └─ 是 → SqlSugar
│
├─ 是否有大量批量操作场景?
│ └─ 是 → SqlSugar
│
├─ 对性能是否极致要求?
│ └─ 是 → Dapper
│
├─ 团队是否 SQL 高手且偏好手写 SQL?
│ └─ 是 → Dapper
│
└─ 追求开发效率,快速交付?
└─ 是 → SqlSugar
8.3 混合使用策略
在实际项目中,两者并非互斥。不少团队采用混合方案:
// 常规 CRUD 用 SqlSugar(开发效率高)
var users = db.Queryable<User>().Where(u => u.Age > 18).ToList();
// 性能关键路径用 Dapper(极致性能)
var report = dapperConn.Query<ReportDto>(
"SELECT /* 复杂报表 SQL */ ...", new { Date = DateTime.Today });
九、一句话总结
SqlSugar 是「SQL 不够,代码来凑」的全能型选手 —— 功能丰富、开箱即用,适合追求开发效率的场景。
Dapper 是「SQL 为王,框架为辅」的极致轻量选手 —— 性能卓越、SQL 可控,适合追求极致性能和 SQL 精细控制的场景。
两者不是替代关系,而是互补关系。选型时请基于项目规模、团队技术栈、性能要求和数据库类型综合判断。

浙公网安备 33010602011771号