从C#中解析PostgreSQL参数化查询中的错误,但在pgAdmin III中有效

时间:2015-01-14 11:59:25

标签: c# postgresql postgis npgsql

我正在尝试从C#执行参数化查询,我收到错误:

  

错误:XX000:解析错误 - 无效几何

提示

  

“POLYGON((:m”< - 几何中位置11处的解析错误

但是当我在pgAdmin III中运行查询时,用它们的值替换参数,查询就可以了。代码是

command.CommandText = "SELECT area_code FROM area WHERE ST_INTERSECTS(ST_GeographyFromText('POLYGON((:minx :miny, :minx :maxy, :maxx :maxy, :maxx :miny, :minx :miny))'), shape) AND area_type_code = :typecode";
command.CommandType = CommandType.Text;
var typeCodeParameter = new NpgsqlParameter
{
    DbType = DbType.String,
    ParameterName = "typecode",
    Value = _typeCode
};
var minxParameter = new NpgsqlParameter
{
    DbType = DbType.Double,
    ParameterName = "minx",
    Value = _minX
};
var minyParameter = new NpgsqlParameter
{
    DbType = DbType.Double,
    ParameterName = "miny",
    Value = _minY
};
var maxxParameter = new NpgsqlParameter
{
    DbType = DbType.Double,
    ParameterName = "maxx",
    Value = _maxX
};
var maxyParameter = new NpgsqlParameter
{
    DbType = DbType.Double,
    ParameterName = "maxy",
    Value = _maxY
};
command.Parameters.Add(typeCodeParameter);
command.Parameters.Add(maxxParameter);
command.Parameters.Add(maxyParameter);
command.Parameters.Add(minxParameter);
command.Parameters.Add(minyParameter);
using (var reader = command.ExecuteReader())
    while (reader.Read())
        areas.Add((string)reader["area_code"]);

,工作查询

SELECT area_code FROM area WHERE ST_INTERSECTS(ST_GeographyFromText('POLYGON((-1.0042576967558934 50.78431084582985, -1.0042576967558934 51.199216033050647, 1.9400782407441057 51.199216033050647, 1.9400782407441057 50.78431084582985, -1.0042576967558934 50.78431084582985))'), shape) AND area_type_code = 'County'

我做错了什么?我该如何设置minx,miny,maxx,maxy参数?

2 个答案:

答案 0 :(得分:2)

问题是你要分离坐标。这些参数不仅仅是在SQL内部(它不仅仅是模板替换),它需要是一个语法上有效的放置参数的地方。一个好的健全性检查是尝试相同的查询,但不是直接用值替换参数,而是使用过程SQL和变量。

您将看到问题是ST_GeographyFromText函数没有扩展输入所在字符串内的参数 - 这是预期的行为。如果你想使用这个功能,你不能在字符串里面使用参数 - 你仍然只需要所有的值并将它们作为一个字符串传递 - 就像你做的那样#&#c; 34;删除参数"。最简单的解决方案可能是将整个字符串作为参数传递,或者只是将参数添加到查询中的字符串中(例如ST_GeographyFromText('POLYGON((' || cast(:minx ...) || '), ' || ... || ')')等)。

似乎你正在转换旧的"连接一堆字符串"带参数化查询的SQL。坚持下去,但你需要考虑语法。就像你不能将子查询放在参数中一样,你不能只将一个值分成两个这样的参数。

所以你需要使用更好的类型,或者有一些辅助转换(比如一个需要两个浮点数的函数,并返回你需要的类型)。

答案 1 :(得分:1)

使用此参数化查询的正确方法是使用一个函数,该函数使用数字参数构建包络,例如ST_MakeEnvelope(xmin, ymin, xmax, ymax)

SELECT area_code
FROM area
WHERE ST_Intersects(ST_MakeEnvelope(:minx, :miny, :maxx, :maxy)::geography, shape)
   AND area_type_code = :typecode;

格式化文本的其他尝试(WKT)速度慢且有损,因为数字会转换为文本,然后再解析为数字。