我有一个使用Npgsql获取PostGIS数据的查询.它的目的是取一个点(x,y坐标)并计算出那个(如果有的话)几何形状.对于数据库中的绝大多数几何,查询工作正常,但至少有一个我得到以下异常:
错误:XX000:使用LWGEOMCOLLECTION类型调用的相关操作.这是不受支持的.
堆栈顶部的跟踪是:
[NpgsqlException(0x80004005):错误:XX000:使用LWGEOMCOLLECTION类型调用的相关操作.这是不受支持的.]
Npgsql.d__0.MoveNext()+ 3160
Npgsql.ForwardsOnlyDataReader.GetNextResponseObject(布尔清理)+808 Npgsql.ForwardsOnlyDataReader.GetNextRow(布尔clearPending)+308 Npgsql.ForwardsOnlyDataReader.Read()+47
所有几何都应该是有效的,因为我调用ST_MakeValid
任何不是,并且当前没有ST_IsValid
返回false.几何图形是通过调用创建的,ST_GeomFromKML
并且在地图上使用WMS通过GeoServer作为栅格图层渲染,或者作为矢量图层使用,ST_AsGeoJSON
因此PostGIS数据似乎没问题.
有什么办法可以修改我的代码或数据来阻止这种情况发生吗?代码失败的部分是读入读取器的部分:
command.CommandText = "SELECT area_code FROM area WHERE ST_INTERSECTS(ST_SetSRID(ST_Point(:x, :y), 4326), shape) AND area_type_code = :typecode";
command.CommandType = CommandType.Text;
var typeCodeParameter = new NpgsqlParameter
{
DbType = DbType.String,
ParameterName = "typecode",
Value = _typeCode
};
var xParameter = new NpgsqlParameter
{
DbType = DbType.Double,
ParameterName = "x",
Value = _x
};
var yParameter = new NpgsqlParameter
{
DbType = DbType.Double,
ParameterName = "y",
Value = _y
};
command.Parameters.Add(typeCodeParameter);
command.Parameters.Add(xParameter);
command.Parameters.Add(yParameter);
using (var reader = command.ExecuteReader())
{
if (reader.Read())
area = new AreaBasic
{
Code = (string)reader["area_code"]
};
}
Run Code Online (Sandbox Code Playgroud)
编辑:进一步的信息.在pgAdmin III中运行带有硬编码值的查询时会发生同样的错误,因此问题不是特定于Npgsql.
这是由于尝试在几何集合上调用相交或包含类型查询,即,您有点,线和多边形(可能是多个)的混合.
至少有一些可能的修复方法.第一个更简单,但看起来有点hacky,这只是简单地将输入几何缓冲为0,这将导致非多边形被删除,因此,在您的情况下,只需将command.commandText更改为
SELECT area_code FROM area WHERE ST_INTERSECTS(ST_SetSRID(ST_Point(:x, :y), 4326),
ST_Buffer(shape, 0)) AND area_type_code = :typecode";
Run Code Online (Sandbox Code Playgroud)
注意,这种方法通常可用于修复无效的几何形状,具有自相交循环的几何形状等.
第二种方法是在形状字段上使用ST_Dump分割成单个几何,然后仅通过ST_GeometryType函数在实际查询中使用多边形.
SELECT area_code
FROM
(SELECT area_code, (ST_Dump(area)).geom FROM area) poly
WHERE ST_INTERSECTS(ST_SetSRID(ST_Point(:x, :y), 4326), poly.geom)
AND ST_GeometryType(poly.geom) = 'ST_Polygon'
OR ST_GeometryType(poly.geom) = 'ST_MultiPolygon'
AND area_type_code = :typecode";
Run Code Online (Sandbox Code Playgroud)
这是未经测试的,因为我无法清楚地对您的数据进行测试,但这些方法在实践中有效.
归档时间: |
|
查看次数: |
3599 次 |
最近记录: |