Dapper不支持表达式树动态拼WHERE,但可通过字符串拼接+参数化查询安全实现:用StringBuilder构建SQL、DynamicParameters管理参数、WHERE 1=1起始、条件统一AND连接,并严禁字符串内联变量防注入。
Dapper 本身不直接支持像 Entity Framework 那样用表达式树动态拼接 WHERE 条件,但可以通过字符串拼接 + 参数化查询的方式安全、灵活地实现动态 WHERE 子句。核心原则是:**条件拼接由代码控制,SQL 参数严格分离,避免 SQL 注入。**
这是最常用、最可控的方式。根据业务逻辑判断哪些条件需要加入 WHERE,逐个追加 SQL 片段,并同步添加对应参数。
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();
如果你希望更接近 ORM 的写法,Dapper.FastCRUD 提供了基于表达式的 Where 构建器,支持链式调用和部分动态条件。
Dapper.FastCRUD.Where(x => x.Name.Contains(name)) 等写法,底层仍转为参数化 SQL注意:它不是官方 Dapper 组件,需评估项目长期维护成本。
为避免重复写拼接逻辑,可封装一个轻量工具类,比如 SqlBuilder,负责管理 WHERE 条件和参数。
List _wheres 和 DynamicParameters _paramsAddIf(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”不是靠魔法,而是靠清晰的条件分支 + 严格的参数隔离。写起来多几行,但稳定、可读、可测试。