Dapper通过集合参数自动展开实现安全高效的IN子句查询,支持任意类型、匿名对象及多集合混合使用,需防范空集合、null及SQL Server参数数限制。
Dapper 本身不直接支持 SQL 中 IN 子句的原生参数化(比如 WHERE id IN @ids),但提供了简洁、安全、高效的方式来实现——核心是利用 Dapper 对集合参数的自动展开能力。
Dapper 能识别传入的数组、List、HashSet 等集合类型,并在生成 SQL 时自动为每个元素生成独立参数,避免 SQL 注入。这是最常用也最推荐的方式。
SELECT * FROM Users WHERE Id IN @ids
@ids 传入 new[] { 1, 2, 3 } 或 new List { 1, 2, 3 }
WHERE Id IN (@ids_0, @ids_1, @ids_2),并绑定对应值如果因特殊原因必须动态拼接(如兼容旧驱动、超大列表需分批),可用 string.Join + SqlMapper.GenerateIn 辅助方法,但务必确保数据已清洗或来自可信源。
Sql
SqlMapper.GenerateInSql 工具方法,可安全生成带参数占位符的 IN 字符串var sql = $"SELECT * FROM Products WHERE CategoryId IN {SqlMapper.GenerateInSql(categoryIds, "@cat")}"
new { cat = categoryIds },不能跳过参数化传入空集合(new int[0])或 null 时,Dapper 默认会抛出异常或生成无效 SQL,需主动防御。
if (!ids.Any()) return new List();
?? Enumerable.Empty() 避免 null 引发异常WHERE 1=1 + 动态添加条件当需要根据对象属性做 IN 查询(如查一批用户名对应的用户),可借助匿名对象或字典传参。
conn.Query("SELECT * FROM Users WHERE Name IN @names", new { names = new[] { "Alice", "Bob" } })
names)必须与 SQL 中的 @names 严格一致WHERE status IN @statuses AND type IN @types)也完全支持,分别传入两个集合即可基本上就这些。Dapper 的 IN 处理不复杂但容易忽略细节,关键是始终用集合参数、避开字符串拼接、留意空值和长度限制。