具有以下查询:
select count(t.*)
from template t
where t.available = true
and exists (select *
from tag
join template_tag on template_tag.tag_id = tag.id
where template_tag.template_id = t.id and tag.name in @tags)
并将dapper动态参数设置为:
new { Tags = new List<string> { "tagExample" } }
运行查询时出现以下错误:
Npgsql.PostgresException:'42601:“ $ 1”或附近的语法错误'
我已经检查了PostgreSQL, Npgsql returning 42601: syntax error at or near "$1",但没有帮助,所以这一定是另一个问题。
最小示例:
const string query = @"
select count(t.*)
from template t
where exists (select *
from template_module tm
where tm.template_id = t.id and tm.module_properties in @props)
";
var parameters = new { props = new List<string> { "{}"} };
var result = await conn.ExecuteScalarAsync<int>(query, parameters);
答案 0 :(得分:0)
例如;
Tags = new List<string> { "tag1","tag2","tag3" }
也许您可以那样使用
string _tags = "('"+string.Join(",',",Tags)+"')";
string query = "select count(t.*)
from template t
where t.available = true
and exists (select *
from tag
join template_tag on template_tag.tag_id = tag.id
where template_tag.template_id = t.id and tag.name in {_tags})";
所以查询就是这样
select count(t.*)
from template t
where t.available = true
and exists (select *
from tag
join template_tag on template_tag.tag_id = tag.id
where template_tag.template_id = t.id and tag.name in ('tag1','tag2','tag3'))
然后执行
更新:基本上相同的推理
这样的sql注入问题的解决方案
public static class SqlCommandExt
{
/// <summary>
/// This will add an array of parameters to a SqlCommand. This is used for an IN statement.
/// Use the returned value for the IN part of your SQL call. (i.e. SELECT * FROM table WHERE field IN ({paramNameRoot}))
/// </summary>
/// <param name="cmd">The SqlCommand object to add parameters to.</param>
/// <param name="paramNameRoot">What the parameter should be named followed by a unique value for each value. This value surrounded by {} in the CommandText will be replaced.</param>
/// <param name="values">The array of strings that need to be added as parameters.</param>
/// <param name="dbType">One of the System.Data.SqlDbType values. If null, determines type based on T.</param>
/// <param name="size">The maximum size, in bytes, of the data within the column. The default value is inferred from the parameter value.</param>
public static SqlParameter[] AddArrayParameters<T>(this SqlCommand cmd, string paramNameRoot, IEnumerable<T> values, SqlDbType? dbType = null, int? size = null)
{
/* An array cannot be simply added as a parameter to a SqlCommand so we need to loop through things and add it manually.
* Each item in the array will end up being it's own SqlParameter so the return value for this must be used as part of the
* IN statement in the CommandText.
*/
var parameters = new List<SqlParameter>();
var parameterNames = new List<string>();
var paramNbr = 1;
foreach (var value in values)
{
var paramName = string.Format("@{0}{1}", paramNameRoot, paramNbr++);
parameterNames.Add(paramName);
SqlParameter p = new SqlParameter(paramName, value);
if (dbType.HasValue)
p.SqlDbType = dbType.Value;
if (size.HasValue)
p.Size = size.Value;
cmd.Parameters.Add(p);
parameters.Add(p);
}
cmd.CommandText = cmd.CommandText.Replace("{" + paramNameRoot + "}", string.Join(",", parameterNames));
return parameters.ToArray();
}
}
并使用它。.
var cmd = new SqlCommand("select count(t.*)
from template t
where t.available = true
and exists (select *
from tag
join template_tag on template_tag.tag_id = tag.id
where template_tag.template_id = t.id and tag.name in ({Tags}))");
cmd.AddArrayParameters("Tags", Tags);