Dapper 本身不提供 MERGE 方法,需手写 T-SQL MERGE 语句并通过 Execute 执行;推荐参数化查询、确保目标表有主键或唯一约束;批量场景宜用表值参数(TVP);也可借助第三方库 DapperPlus 的 BulkMerge 实现自动化。

Dapper 本身不直接提供 MERGE 方法,它是一个轻量级微 ORM,只扩展 IDbConnection,提供 Query、Execute 等基础方法。要执行 SQL Server 的 MERGE 语句,你得手写 T-SQL 并用 Execute 执行——和写普通 INSERT/UPDATE/DELETE 一样,只是 SQL 内容换成 MERGE。
Dapper 执行 MERGE 的基本方式
核心就是:拼好标准的 T-SQL MERGE 语句,用参数化方式传参,调用 connection.Execute(sql, parameters)。
- MERGE 是原生 T-SQL 语法,Dapper 不封装它,也不解析它,只负责安全传参和执行
- 必须确保目标表有主键或唯一约束,MERGE 的
ON条件才可靠 - 推荐使用命名参数(如
@Id、@Name),避免字符串拼接引发 SQL 注入或类型错误
带参数的 MERGE 示例(单条记录)
比如同步一个用户信息,存在则更新,不存在则插入:
string sql = @"
MERGE Users AS target
USING (SELECT @Id AS Id, @Name AS Name, @Email AS Email) AS source
ON target.Id = source.Id
WHEN MATCHED THEN
UPDATE SET Name = source.Name, Email = source.Email
WHEN NOT MATCHED THEN
INSERT (Id, Name, Email) VALUES (source.Id, source.Name, source.Email);";
var parameters = new { Id = 123, Name = "李四", Email = "lisi@example.com" };
int affected = connection.Execute(sql, parameters);
注意:SQL 中的 USING (...) 子查询是常见写法,让参数能被 MERGE 引用;也可以用临时表或表值参数(见下一条)。
批量 MERGE:用表值参数(TVP)更高效
一次处理几百上千条记录时,别循环 Execute,改用 TVP + MERGE。步骤分三步:
- 在数据库中创建用户定义表类型,例如:
CREATE TYPE UserMergeType AS TABLE (Id INT, Name NVARCHAR(50), Email NVARCHAR(100)) - C# 中构建
DataTable,填入数据,再包装成SqlMapper.TableValuedParameter - SQL 中把
USING @tvp替换掉子查询,MERGE 就自动批量处理整张表
这是真正高性能的批量 MERGE 方式,比逐条 Execute 快一个数量级以上。
用 Dapper Plus 实现 MERGE(第三方增强库)
如果你不想手写 MERGE SQL,可以引入 Z.EntityFramework.Extensions 生态下的 DapperPlus 包(非官方,但广泛使用):
- 支持
BulkMerge()方法,底层自动生成并执行 MERGE 语句 - 可链式配置:指定主键、映射表名、处理一对多关系等
- 示例:
connection.BulkMerge(users)即完成“存在则更新、不存在则插入” - 注意:需额外安装
DapperPlusNuGet 包,且仅支持 SQL Server(部分版本支持 PostgreSQL)
本质上它是帮你生成并执行 MERGE 的封装层,不是 Dapper 原生能力。
基本上就这些。手写 MERGE 灵活可控,TVP + MERGE 适合大批量,Dapper Plus 适合想省事又接受第三方依赖的场景。










