NPGSQL:使用 LWGEOMCOLLECTION 类型调用的关联操作

Posted

技术标签:

【中文标题】NPGSQL:使用 LWGEOMCOLLECTION 类型调用的关联操作【英文标题】:NPGSQL: Relate Operation called with a LWGEOMCOLLECTION type 【发布时间】:2015-04-10 18:08:59 【问题描述】:

我有一个使用 Npgsql 获取 PostGIS 数据的查询。其目的是获取一个点(x,y 坐标)并计算出该点处的几何形状(如果有的话)。对于数据库中的绝大多数几何,查询都可以正常工作,但至少有一个我得到以下异常:

错误:XX000:使用 LWGEOMCOLLECTION 类型调用的关联操作。 这是不受支持的。

堆栈跟踪的顶部是:

[NpgsqlException (0x80004005): 错误: XX000: 调用关联操作 具有 LWGEOMCOLLECTION 类型。这是不受支持的。] Npgsql.d__0.MoveNext() +3160 Npgsql.ForwardsOnlyDataReader.GetNextResponseObject(布尔清理) +808 Npgsql.ForwardsOnlyDataReader.GetNextRow(Boolean clearPending) +308 Npgsql.ForwardsOnlyDataReader.Read() +47

所有几何图形都应该是有效的,因为我在任何不合法的几何图形上调用 ST_MakeValid,并且当前没有 ST_IsValid 返回 false 的几何图形。几何图形是通过调用ST_GeomFromKML 创建的,并在地图上通过GeoServer 使用WMS 作为栅格图层或使用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"]
        ;

编辑: 更多信息。在 pgAdmin III 中使用硬编码值运行查询时会发生相同的错误,因此问题不是 Npgsql 特定的。

【问题讨论】:

【参考方案1】:

这是由于尝试在几何集合上调用 intersects 或 contains 类型查询,即您有一些混合点、线和多边形(可能是多个)。

至少有几个可能的修复方法。第一个更简单,但似乎有点 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";

请注意,这种方法通常可用于修复无效几何图形、具有自相交循环的几何图形等。

第二种方法是在你的 shape 字段上使用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";

这是未经测试的,因为我无法根据您的数据清楚地对此进行测试,但这些方法在实践中有效。

【讨论】:

以上是关于NPGSQL:使用 LWGEOMCOLLECTION 类型调用的关联操作的主要内容,如果未能解决你的问题,请参考以下文章

NPGSQL:使用 LWGEOMCOLLECTION 类型调用的关联操作

使用 npgsql 在 c# 中插入

like 使用参数的 npgsql 语句

Npgsql 如何处理失败的事务?

在 NpgSql 中使用 BeginBinaryImport 插入位数据类型进行批量数据插入

Entity Framework 5.0 PostgreSQL (Npgsql) 默认连接工厂