Dapper怎么处理SQL的MERGE语句 Dapper执行MERGE操作教程

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

Dapper 本身不直接提供 MERGE 方法,它是一个轻量级微 ORM,只扩展 IDbConnection,提供 QueryExecute 等基础方法。要执行 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) 即完成“存在则更新、不存在则插入”
  • 注意:需额外安装 DapperPlus NuGet 包,且仅支持 SQL Server(部分版本支持 PostgreSQL)

本质上它是帮你生成并执行 MERGE 的封装层,不是 Dapper 原生能力。

基本上就这些。手写 MERGE 灵活可控,TVP + MERGE 适合大批量,Dapper Plus 适合想省事又接受第三方依赖的场景。