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。
核心就是:拼好标准的 T-SQL MERGE 语句,用参数化方式传参,调用 connection.Execute(sql, parameters)。
ON 条件才可靠@Id、@Name),避免字符串拼接引发 SQL 注入或类型错误比如同步一个用户信息,存在则更新,不存在则插入:
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 引用;也可以用临时表或表值参数(见下一条)。
一次处理几百上千条记录时,别循环 Execute,改用 TVP + MERGE。步骤分三步:
建用户定义表类型,例如:CREATE TYPE UserMergeType AS TABLE (Id INT, Name NVARCHAR(50), Email NVARCHAR(100))
DataTable,填入数据,再包装成 SqlMapper.TableValuedParameter
USING @tvp 替换掉子查询,MERGE 就自动批量处理整张表这是真正高性能的批量 MERGE 方式,比逐条 Execute 快一个数量级以上。
如果你不想手写 MERGE SQL,可以引入 Z.EntityFramework.Extensions 生态下的 DapperPlus 包(非官方,但广泛使用):
BulkMerge() 方法,底层自动生成并执行 MERGE 语句connection.BulkMerge(users) 即完成“存在则更新、不存在则插入”DapperPlus NuGet 包,且仅支持 SQL Server(部分版本支持 PostgreSQL)本质上它是帮你生成并执行 MERGE 的封装层,不是 Dapper 原生能力。
基本上就这些。手写 MERGE 灵活可控,TVP + MERGE 适合大批量,Dapper Plus 适合想省事又接受第三方依赖的场景。