如何使用Dapper实现MySQL中基于行构造器的IN查询?
在Dapper中实现MySQL多列IN查询
问题说明
MySQL原生支持多列IN查询,语法示例:
SELECT * FROM test WHERE (a, b) IN ((1,2), (3,4))
但直接用Dapper传递元组列表作为参数时会报错,示例代码:
connection.QueryAsync("SELECT * FROM test where (a, b) IN @params)", new { params = myList.Select(x => (x.a, x.b)) });
抛出NotSupportedException,错误信息:
The member of type <>f__AnonymousType18'2[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] cannot be used as a parameter value
原因是Dapper默认不支持将匿名元组类型直接作为IN参数绑定。
可行解决方案
方案1:动态生成参数占位符
手动为每个元组的列生成独立参数,避免匿名元组的解析问题:
var items = myList.Select(x => new { x.a, x.b }).ToList(); // 生成带占位符的SQL var sqlTemplate = "SELECT * FROM test WHERE (a, b) IN ({0})"; var paramPlaceholders = string.Join(", ", items.Select((_, index) => $"(@a{index}, @b{index})")); var sql = string.Format(sqlTemplate, paramPlaceholders); // 绑定参数 var parameters = new DynamicParameters(); for (int i = 0; i < items.Count; i++) { parameters.Add($"a{i}", items[i].a); parameters.Add($"b{i}", items[i].b); } // 执行查询 var result = await connection.QueryAsync(sql, parameters);
方案2:使用Dapper.QueryBuilder扩展
引入Dapper.QueryBuilder NuGet包后,可简化多列IN的参数绑定:
var query = connection.QueryBuilder($@" SELECT * FROM test WHERE (a, b) IN ({@items.Select(x => new { x.a, x.b })}) "); var result = await query.QueryAsync();
该扩展会自动处理参数占位符和绑定,无需手动拼接。
方案3:转换为等价OR条件(小数据量适用)
当待匹配的元组数量不多时,可将多列IN转换为多个(a=? AND b=?)的OR组合:
var conditions = myList.Select((item, index) => $"a = @a{index} AND b = @b{index}"); var sql = $"SELECT * FROM test WHERE {string.Join(" OR ", conditions)}"; var parameters = new DynamicParameters(); for (int i = 0; i < myList.Count; i++) { parameters.Add($"a{i}", myList[i].a); parameters.Add($"b{i}", myList[i].b); } var result = await connection.QueryAsync(sql, parameters);
内容的提问来源于stack exchange,提问作者Mathias
相关产品推荐
相关产品推荐

