Skip to content
Go back

Dapper 配 ASP.NET Core 10,到底适合什么场景

Dapper 与 ASP.NET Core 10 数据访问概念图

每隔一阵,Dapper 都会被重新问一次:现在都已经 Entity Framework Core 这么成熟了,为什么还有人坚持手写 SQL、坚持用 micro-ORM?

这篇讲 Dapper in Depth with ASP.NET Core 10 的文章,其实给了一个挺典型的答案:因为有一类系统,真的更在乎可控、直白和性能,而不是 ORM 帮你包办一切。

它不是那种特别有新理论的文章,但对很多还在纠结“EF Core 还是 Dapper”的人来说,价值正好在于它把 Dapper 的使用场景、常见能力和工程结构重新摆了一遍。你看完不会突然学会什么魔法,但会更清楚:Dapper 到底强在哪,麻烦又在哪。

Dapper 的核心吸引力,始终没变

文章一开始对 Dapper 的定义很传统:它是 Stack Overflow 团队做的 micro-ORM,建立在 ADO.NET 之上,抽象很薄,速度很快,直接把 SQL 结果映射到强类型对象。

这些话大家都听过,但真正重要的是,它背后的 trade-off 也一直没变:

这其实就是 Dapper 的全部魅力和全部代价。

它吸引人的地方,不是“它比 EF Core 高级”,而是它更诚实。你写什么 SQL,它就跑什么 SQL。不会替你做很多聪明事,也不会偷偷帮你把复杂度藏起来。对于想精确控制数据访问层的人,这种直白反而是优点。

它最适合的,不是所有系统

原文列了一些典型场景:高流量 API、微服务、金融系统、报表平台、读多写少的系统。

这个判断基本靠谱。

因为 Dapper 真正舒服的地方,往往出现在下面这类情况:

比如报表接口、分析接口、复杂筛选列表、聚合查询、一些典型的后台服务,这些地方 Dapper 常常很顺手。你写一条清晰的 SQL,参数化执行,映射回 DTO 或模型,事情就结束了。

但如果你的系统更依赖这些能力:

那 Dapper 就不会那么“轻松”,而会开始显得手工活偏多。

所以更准确的说法不是“Dapper 更好”,而是:Dapper 对某些后端场景更顺手。

文章最实用的部分,是把常用方法和高级能力串起来了

这篇文章对 Dapper 的方法体系梳理得比较全。从 Query<T>()QueryAsync<T>()Execute() 一直到 QueryMultiple()、multi-mapping、transactions、stored procedures、bulk operations`,基本把大家平时真会碰到的东西都扫了一遍。

如果你已经用过 Dapper,这部分不算新鲜;但如果你只停留在“我知道 Dapper 能查表”的阶段,它至少能帮你建立一个更完整的认知:Dapper 不只是查一行、改一行,它也能承接一些复杂一点的数据库交互。

尤其下面几块比较值得记:

QueryMultiple 很适合聚合接口

原文举了一个典型例子:一次查询里同时拿 product、reviews、category。

这类能力在 API 层其实挺常见。与其跑三次往返,不如一口气查出多个结果集,再逐个读取。对于 dashboard、详情页、聚合接口,这类写法很实用。

Multi-mapping 解决 JOIN 后的对象映射

这块也很典型。很多人一开始用 Dapper 会觉得 JOIN 之后映射回对象不够优雅,但它其实提供了多对象映射能力,只是比完整 ORM 更显式、更手工一点。

换句话说,Dapper 不是做不到关系映射,只是它要求你自己更清楚地写出“怎么拼”。

Transaction 依然是 ADO.NET 那套现实

这一点反而挺好:Dapper 没有发明另一套 transaction 哲学,它基本还是沿用 IDbTransaction。这意味着你掌控感更强,但也意味着你不能偷懒。

这很适合订单、库存、支付之类强一致性场景,但前提是你团队得真懂事务,不是把 BeginTransaction() 当护身符念咒。

文章里的“仓储模式 + 服务层”写法,能用,但别神化

原文也给了一个比较标准的 ASP.NET Core Web API 分层:

这套结构当然能用,而且对很多中小型项目来说很熟悉、很稳。

但说实话,Dapper 和 repository pattern 的关系没有很多文章写得那么天作之合。

因为 Dapper 的一个特点就是:SQL 本身常常就是业务行为的一部分。如果你把 repository 抽得太厚,最后很容易写出一堆只是帮你转发 SQL 的接口,既没减少复杂度,也没增加多少可维护性。

所以我觉得更实在的态度是:

换句话说,Dapper 最怕的不是 SQL 多,而是结构装得太优雅,结果每层都只是在传话。

它对比 EF Core 的意义,不是赢,而是明确边界

原文多次暗示 Dapper 和 EF Core 的差异,这其实是多数读者最关心的部分。

我觉得最该抓住的不是“谁更好”,而是这一句:

Dapper 适合你想自己掌控 SQL 的时候;EF Core 适合你愿意用更高抽象换开发便利的时候。

很多团队会在这两者之间摇摆,核心原因不是技术优劣,而是团队的真实能力和项目的真实约束不同。

如果团队里:

那 Dapper 会越用越顺。

但如果团队更依赖:

那 EF Core 更容易把整体协作成本压下来。

所以这不是“轻量击败重量”的故事,而是:你到底想把复杂度放在哪一层。

真正需要警惕的是“手写 SQL 的自信膨胀”

文章里也提到参数化查询、防 SQL 注入、异步方法、事务这些好习惯,这些当然都对。

但 Dapper 真正危险的地方,不是大家不知道这些概念,而是很容易在“我自己写 SQL,所以我更懂数据库”这件事上过度自信。

现实里,很多 Dapper 项目后面会遇到的问题其实是:

也就是说,Dapper 不是更低复杂度,而是把复杂度从 ORM 机制里拿出来,摆到你自己面前。

如果团队不打算认真管这件事,那“手写 SQL 的掌控感”最后可能会变成“到处都是没人敢动的查询字符串”。

这篇文章最值得带走的判断

如果把这篇长文压成一句最实用的话,我觉得大概是:

Dapper 不是用来替代所有 ORM 的,它是给那些明确知道自己为什么要写 SQL 的团队准备的。

这句话很重要。

因为很多工具争论最后都会失焦,变成“哪个更现代”“哪个性能更高”“哪个公司更常用”。但 Dapper 的问题从来不在这些标签,而在于:你的系统是不是需要这种薄抽象,你的团队是不是能驾驭它带来的裸露复杂度。

如果答案是“是”,那 Dapper 在 ASP.NET Core 10 这种高性能 Web API 场景里,依然非常能打。

如果答案是“不是”,那也没必要为了追求“轻量”而硬上。

参考


Tags


Previous

VS Code 的 browser agent tools,开始让 agent 自己下场测页面

Next

Leanstral 在做什么:给 vibe coding 加上可验证性