用匿名对象传参是最安全的默认选择:Dapper通过参数化执行防止SQL注入,WHERE需写@参数名并配匿名对象,IN子句传数组、LIKE拼通配符在C#变量中、多条件宁可传null也不拼SQL;DynamicParameters仅补足能力缺口,非更高级防注入方案;ORDER BY等语法结构不可参数化,须白名单校验后拼接;空IN数组和NULL处理需特别注意。

用匿名对象传参是最安全的默认选择
Dapper 的 Query、Execute 等方法原生支持匿名对象,这是绝大多数场景下防注入的第一道防线。只要 SQL 字符串里只出现 @参数名,所有值都来自匿名对象,Dapper 就会走底层 ADO.NET 的参数化执行路径,用户输入哪怕包含 ' OR 1=1 -- 也会被当作文本数据处理。
- WHERE 条件必须写成
"WHERE Email = @Email",再配new { Email = userInput },绝不能写成$"WHERE Email = '{userInput}'" - IN 子句直接传数组:
new { Ids = new[] { 1, 2, 3 } },Dapper 自动展开为WHERE Id IN (@Ids0, @Ids1, @Ids2) - LIKE 模糊匹配要把通配符拼在 C# 变量里:
new { name = $"%{search}%" },SQL 写"Name LIKE @name",而不是在 SQL 里硬写"Name LIKE '%{search}%'" - 多条件组合时,宁可让部分参数为
null,也别拼 SQL 字符串——Dapper 对null参数不报错,只是不参与 WHERE 绑定
DynamicParameters 是为输出参数和类型控制准备的
匿名对象覆盖不了所有需求,但 DynamicParameters 不是“更高级的防注入方案”,它只是补足能力缺口的工具,安全性完全取决于你怎么用。
- 需要存储过程输出参数时,必须用
Add("@Total", dbType: DbType.Int32, direction: ParameterDirection.Output),不能靠out int或返回值模拟 - 传
DateTimeOffset或Guid时,某些数据库驱动(如旧版 Npgsql)可能误判类型,显式指定dbType可避免隐式转换失败 - 动态字段名(比如按请求决定排序字段)必须先校验白名单,再调用
Add("@SortField", safeValue),不能把用户输入直接塞进Add的第一个参数 - 绝对不要用
AddWithValue往里塞字符串拼接结果——AddWithValue本身不危险,但人容易在它前面先做字符串拼接
ORDER BY、表名、列名这些根本不能参数化
@param 只能替换值,不能替换 SQL 语法结构。这部分 Dapper 完全不干预,也不报错,你拼错了它就执行错,拼恶意了它就执行恶意的。
-
ORDER BY @SortColumn是非法语法,SQL Server/PostgreSQL 都会直接报错;MySQL 虽然允许,但属于未定义行为,不可依赖 - 真实做法是:
if (!new[] { "Name", "CreatedAt", "Status" }.Contains(sort)) throw new ArgumentException("Invalid sort field");,然后拼$"ORDER BY {sort}" - 表名、schema、视图名同理,必须来自配置文件、枚举或硬编码,绝不能来自 HTTP 查询参数或表单字段
- 这类拼接一旦放开,等于在防火墙上凿了个洞——Dapper 对它毫无感知,也不会加任何防护
最容易被忽略的其实是 IN 子句和 NULL 处理
很多人以为 IN 子句写对了就万事大吉,其实边界情况极多,稍不注意就掉坑里。
- 空数组传给
new { Ids = new int[0] },Dapper 会生成WHERE Id IN (),多数数据库直接报语法错误;得提前判断if (!ids.Any()) return Enumerable.Empty<t>();</t> -
NULL值在 SQL 中要显式写成IS NULL,不能靠@value占位符自动适配;比如"WHERE DeletedAt IS NULL"和"WHERE DeletedAt = @DeletedAt"是两回事 - 混合使用
IN和OR逻辑时,括号优先级容易出错,建议用Dapper.SqlBuilder这类辅助类管理片段,而不是手拼 - 参数名大小写敏感:SQL 里写
@Email,匿名对象里就得是new { Email = ... },email或EMAIL都会绑定失败,返回空结果而非报错,排查起来很隐蔽

















