2015-02-10 17 views
6

Ho una query che recupera i dati PostGIS utilizzando Npgsql. Il suo scopo è quello di prendere un punto (x, y coordinate) e capire quale (se c'è) la geometria è in quel punto. Per la stragrande maggioranza delle geometrie nel database query funziona bene, ma per almeno un'ottengo la seguente eccezione:NPGSQL: operazione correlata chiamata con un tipo LWGEOMCOLLECTION

ERROR: XX000: Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported.

con la parte superiore dell'essere dello stack:

[NpgsqlException (0x80004005): ERROR: XX000: Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported.]
Npgsql.d__0.MoveNext() +3160
Npgsql.ForwardsOnlyDataReader.GetNextResponseObject(Boolean cleanup) +808 Npgsql.ForwardsOnlyDataReader.GetNextRow(Boolean clearPending) +308 Npgsql.ForwardsOnlyDataReader.Read() +47

Tutte le geometrie dovrebbe essere valido come chiamo ST_MakeValid su quelli che non lo sono e non ci sono attualmente nessuno dove ST_IsValid restituisce false. La geometria è stata creata chiamando lo ST_GeomFromKML ed è reso bene su una mappa come livello raster utilizzando WMS tramite GeoServer o come livello vettoriale utilizzando ST_AsGeoJSON in modo che i dati PostGIS sembrino essere corretti.

Esiste un modo per modificare il mio codice oi miei dati per impedire che ciò accada? La parte del codice difetto è la parte in cui il lettore viene letto in:

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"] 
     }; 
} 

EDIT: ulteriori informazioni. Lo stesso errore si verifica quando si esegue la query con valori hard coded in pgAdmin III, quindi il problema non è specifico per Npgsql.

risposta

6

Ciò è dovuto al tentativo di chiamare un intersecato o contiene query di tipo su una raccolta geometria, cioè, dove si dispone di una combinazione di punti, linee e poligoni (possibilmente multi).

Ci sono, almeno, un paio di possibili correzioni. Il primo è più semplice, ma sembra un po 'hacky, che è semplicemente quello di bufferare la geometria di input prima di 0, il che comporterà la rimozione di non poligoni, quindi, nel tuo caso, semplicemente cambiando command.commandText in

SELECT area_code FROM area WHERE ST_INTERSECTS(ST_SetSRID(ST_Point(:x, :y), 4326), 
ST_Buffer(shape, 0)) AND area_type_code = :typecode"; 

Nota: questo approccio può essere spesso utilizzato per correggere le geometrie non valide, quelle con loop autointersecanti e simili.

Il secondo approccio consiste nell'utilizzare ST_Dump nel campo forma per suddividerle in singole geometrie e quindi utilizzare solo poligoni nella query effettiva tramite la funzione 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"; 

Questo è testato, come non riesco a provare questo su di voi i dati in modo chiaro, ma questi approcci funzionano nella pratica.