Dapper不支持表达式树动态拼WHERE,但可通过字符串拼接+参数化查询安全实现:用StringBuilder构建SQL、DynamicParameters管理参数、WHERE 1=1起始、条件统一AND连接,并严禁字符串内联变量防注入。

Dapper 本身不直接支持像 Entity Framework 那样用表达式树动态拼接 WHERE 条件,但可以通过字符串拼接 + 参数化查询的方式安全、灵活地实现动态 WHERE 子句。核心原则是:**条件拼接由代码控制,SQL 参数严格分离,避免 SQL 注入。**
手动拼接 SQL + 动态参数字典
这是最常用、最可控的方式。根据业务逻辑判断哪些条件需要加入 WHERE,逐个追加 SQL 片段,并同步添加对应参数。
- 用 StringBuilder 或字符串插值(C# 10+)逐步构建 SQL
- 用 IDictionary
或 DynamicParameters 收集参数,确保每个参数名唯一且带前缀(如 @name、@age) - WHERE 后第一个条件用
WHERE 1=1开头,后续条件统一用AND连接,简化逻辑判断
示例:
var sql = new StringBuilder("SELECT * FROM Users WHERE 1=1");
var parameters = new DynamicParameters();
if (!string.IsNullOrWhiteSpace(name))
{
sql.Append(" AND Name LIKE @name");
parameters.Add("@name", $"%{name}%", DbType.String);
}
if (age.HasValue)
{
sql.Append(" AND Age = @age");
parameters.Add("@age", age.Value, DbType.Int32);
}
if (isActive.HasValue)
{
sql.Append(" AND IsActive = @isActive");
parameters.Add("@isActive", isActive.Value, DbType.Boolean);
}
var users = connection.Query(sql.ToString(), parameters).ToList();
使用 Dapper.FastCRUD(第三方扩展)
如果你希望更接近 ORM 的写法,Dapper.FastCRUD 提供了基于表达式的 Where 构建器,支持链式调用和部分动态条件。
- 需安装 NuGet 包:
Dapper.FastCRUD - 支持
.Where(x => x.Name.Contains(name))等写法,底层仍转为参数化 SQL - 对简单动态场景友好,但复杂逻辑(如 OR 分组、嵌套括号)仍需手写 SQL
注意:它不是官方 Dapper 组件,需评估项目长期维护成本。
封装通用动态查询辅助类
为避免重复写拼接逻辑,可封装一个轻量工具类,比如 SqlBuilder,负责管理 WHERE 条件和参数。
- 内部维护
List和_wheres DynamicParameters _params - 提供
AddIf(string condition, string paramName, object value)方法,自动跳过 null/empty 值 - 最终调用
BuildSelectSql(string table, string fields = "*")返回完整 SQL 和参数
这样业务层只需关注“要不要加这个条件”,不用操心 SQL 拼写和参数命名冲突。
慎用字符串格式化或内联变量
绝对不要这样写:
// ❌ 危险!SQL 注入漏洞
string sql = $"SELECT * FROM Users WHERE Name = '{name}'";
也不建议用 $"AND Age = {age}" 直接拼数值——即使 int 看似安全,一旦类型变更或传入恶意字符串就失控。Dapper 的安全性完全依赖参数化,绕过它就等于放弃防护底线。
基本上就这些。Dapper 的“动态 WHERE”不是靠魔法,而是靠清晰的条件分支 + 严格的参数隔离。写起来多几行,但稳定、可读、可测试。










