使用Dapper SQL Builder构建动态WHERE子句的BETWEEN语法问题
你的问题核心在于Dapper SqlBuilder对数组类型参数的自动转换逻辑:当你传递一个数组作为参数时,它会默认把这个参数当成IN子句的参数集合,自动将@colparam替换成(@colparam1,@colparam2)——这对IN语法很友好,但完全不符合BETWEEN需要@start AND @end的语法要求。下面给你几个针对性的解决方案:
方案1:拆分数组为独立参数(最直观的写法)
既然BETWEEN需要两个明确的边界值,直接从接收的数组中取出两个元素,分别绑定到两个参数即可:
SqlBuilder sqlBuilder = new SqlBuilder(); var sqlTemplate = sqlBuilder.AddTemplate(@"Select * from tbl_example /**Where**/"); // 假设paramValue是长度为2的整数数组 var rangeStart = paramValue[0]; var rangeEnd = paramValue[1]; // 明确写出BETWEEN的两个参数和AND连接符 sqlBuilder.Where(@"Col BETWEEN @rangeStart AND @rangeEnd", new { rangeStart, rangeEnd }); con.Query(sqlTemplate.RawSql, sqlTemplate.Parameters);
这样生成的SQL会是你期望的:Select * from tbl_example Where Col BETWEEN @rangeStart AND @rangeEnd,参数也会正确绑定两个值。
方案2:使用DynamicParameters灵活绑定参数
如果需要更动态的参数管理(比如参数数量不确定,但这里固定是2个),可以用Dapper的DynamicParameters类来手动添加参数:
SqlBuilder sqlBuilder = new SqlBuilder(); var sqlTemplate = sqlBuilder.AddTemplate(@"Select * from tbl_example /**Where**/"); var parameters = new DynamicParameters(); parameters.Add("startVal", paramValue[0]); parameters.Add("endVal", paramValue[1]); sqlBuilder.Where(@"Col BETWEEN @startVal AND @endVal", parameters); con.Query(sqlTemplate.RawSql, sqlTemplate.Parameters);
这种写法在处理复杂参数场景时更灵活,同时也能完全避免Dapper的自动数组转换逻辑。
方案3:手动构造参数字典(适用于通用场景)
如果你的代码需要兼容更多参数情况,可以手动构造参数字典,明确指定每个参数名:
SqlBuilder sqlBuilder = new SqlBuilder(); var sqlTemplate = sqlBuilder.AddTemplate(@"Select * from tbl_example /**Where**/"); var paramDict = new Dictionary<string, object>(); // 遍历数组,给每个元素分配独立的参数名 for (int i = 0; i < paramValue.Length; i++) { paramDict.Add($"colParam{i+1}", paramValue[i]); } // 针对BETWEEN语法,直接写出两个参数的占位符 sqlBuilder.Where(@"Col BETWEEN @colParam1 AND @colParam2", paramDict); con.Query(sqlTemplate.RawSql, sqlTemplate.Parameters);
这个方法的优势是可以适配参数数量变化的场景,但需要确保数组长度符合BETWEEN的要求(必须是2个元素)。
为什么原写法会出错?
Dapper SqlBuilder的Where方法内部有一套参数转换逻辑:当检测到参数是数组或集合类型时,会自动将单个参数占位符替换为括号包裹的多参数形式(比如@param→(@param1,@param2)),这是为了简化IN子句的写法,但这套逻辑不会区分BETWEEN和IN的语法差异,所以才会生成不符合预期的SQL。
内容的提问来源于stack exchange,提问作者MahPa

