Dapper如何动态构建查询条件 Dapper动态WHERE子句方法

13次阅读

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

Dapper如何动态构建查询条件 Dapper动态WHERE子句方法

Dapper 本身不直接支持像 Entity Framework 那样用表达式树动态拼接 WHERE 条件,但可以通过字符串拼接 + 参数化查询的方式安全、灵活地实现动态 WHERE 子句。核心原则是:**条件拼接由代码控制,SQL 参数严格分离,避免 SQL 注入。**

手动拼接 SQL + 动态参数字典

这是最常用、最可控的方式。根据业务逻辑判断哪些条件需要加入 WHERE,逐个追加 SQL 片段,并同步添加对应参数。

  • StringBuilder 或字符串插值(C# 10+)逐步构建 SQL
  • IDictionaryDynamicParameters 收集参数,确保每个参数名唯一且带前缀(如 @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 _wheresDynamicParameters _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”不是靠魔法,而是靠清晰的条件分支 + 严格的参数隔离。写起来多几行,但稳定、可读、可测试。

text=ZqhQzanResources