PostgreSQL+Dapper绑定VALUES子串时多余双引号问题求助
解决方案:PostgreSQL+Dapper拼接VALUES出现多余双引号问题
问题根源
你遇到的多余双引号,是因为直接用string.Format拼接后,误将拼接结果作为参数传递给Dapper,Dapper会自动给字符串参数添加引号进行转义;另外手动拼接SQL还存在严重的SQL注入风险,不推荐这么做。
推荐解决方案(无注入风险,彻底解决引号问题)
方案1:多参数化VALUES子句
通过为每个GameId和Count单独创建参数,让Dapper自动处理类型和转义,完全避免手动拼接字符串:
using Dapper; using System.Data; using Npgsql; // PostgreSQL的ADO.NET驱动 // 准备参数集合 var parameters = new DynamicParameters(); var valueItems = new List<string>(); int paramIndex = 0; foreach (var item in ListGameIdCountResponse) { // 生成唯一参数名 var gameIdParam = $"@GameId{paramIndex}"; var countParam = $"@Count{paramIndex}"; // 添加参数(Dapper会自动处理Guid类型映射) parameters.Add(gameIdParam, item.GameId, DbType.Guid); parameters.Add(countParam, item.Count, DbType.Int32); // 构造VALUES中的子句 valueItems.Add($"({gameIdParam}, {countParam})"); paramIndex++; } // 拼接完整SQL var sql = $@"SELECT g.""Name"", g.""Id"" FROM ""Games"" g LEFT JOIN (VALUES {string.Join(",", valueItems)}) AS TrendingGameCount (GameId, Count) ON g.""Id"" = TrendingGameCount.GameId::uuid ORDER BY TrendingGameCount.Count DESC"; // 执行查询 using var connection = new NpgsqlConnection("你的连接字符串"); var result = connection.Query<YourResultModel>(sql, parameters);
方案2:使用PostgreSQL数组+unnest函数(更简洁)
利用PostgreSQL的数组特性,直接传递GameId和Count数组,通过unnest函数展开为临时表:
using Dapper; using Npgsql; // 提取数组数据 var gameIds = ListGameIdCountResponse.Select(p => p.GameId).ToArray(); var counts = ListGameIdCountResponse.Select(p => p.Count).ToArray(); // 编写参数化SQL var sql = @"SELECT g.""Name"", g.""Id"" FROM ""Games"" g LEFT JOIN unnest(@GameIds, @Counts) AS TrendingGameCount (GameId, Count) ON g.""Id"" = TrendingGameCount.GameId::uuid ORDER BY TrendingGameCount.Count DESC"; // 执行查询(Dapper自动映射.NET数组到PostgreSQL数组) using var connection = new NpgsqlConnection("你的连接字符串"); var result = connection.Query<YourResultModel>(sql, new { GameIds = gameIds, Counts = counts });
不推荐的临时方案(仅作参考,有注入风险)
如果一定要坚持手动拼接(仅当GameId是数据库返回的Guid、Count是整数,完全不可控时勉强可用),需要直接拼接成完整SQL字符串后传给Dapper,而不是把拼接结果作为参数:
// 注意:此方法存在SQL注入风险,禁止用于用户输入相关场景 var valuesClause = string.Join(',', ListGameIdCountResponse.Select(p => $"('{p.GameId}', {p.Count})")); var sql = $@"SELECT g.""Name"", g.""Id"" FROM ""Games"" g LEFT JOIN (VALUES {valuesClause}) AS TrendingGameCount (GameId, Count) ON g.""Id"" = TrendingGameCount.GameId::uuid ORDER BY TrendingGameCount.Count DESC"; using var connection = new NpgsqlConnection("你的连接字符串"); var result = connection.Query<YourResultModel>(sql);
内容的提问来源于stack exchange,提问作者Choi Xong Zong
相关产品推荐
相关产品推荐

