![]() |
VOOZH | about |
The NetTopologySuite (NTS) plugin enables spatial data support in the Npgsql EF Core provider by integrating with PostgreSQL's PostGIS extension. This plugin provides type mappings between NTS geometry types and PostGIS spatial types, and translates LINQ spatial operations into PostGIS SQL functions.
The NTS plugin is a separate package (Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite) that extends the core provider through the plugin architecture. It registers spatial type mappings via IRelationalTypeMappingSourcePlugin and translates spatial method calls via IMethodCallTranslatorPlugin.
The plugin integrates at several extension points:
NpgsqlNetTopologySuiteTypeMappingSourcePlugin registers mappings for NTS types (Point, Polygon, etc.) to PostGIS types (geometry, geography).ST_Distance, ST_Intersects, and ST_Collect.Sources: src/EFCore.PG.NTS/Extensions/NpgsqlNetTopologySuiteServiceCollectionExtensions.cs13-37 src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs14-15
The NTS plugin is distributed as a separate NuGet package that references both the core Npgsql EF Core provider and the Npgsql.NetTopologySuite ADO.NET plugin. The PostGIS extension must be installed in your PostgreSQL database:
Enable the NTS plugin by calling UseNetTopologySuite() on the NpgsqlDbContextOptionsBuilder:
Configuration options are managed via NpgsqlNetTopologySuiteOptionsExtension and INpgsqlNetTopologySuiteSingletonOptions:
| Option | Description | File Reference |
|---|---|---|
HandleOrdinates | Specifies which coordinate dimensions to handle (X, Y, Z, M) | src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs39 |
IsGeographyDefault | Maps CLR types to geography instead of geometry | src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs47 |
PrecisionModel | NTS Precision model to use for geometries | src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs31 |
Sources: src/EFCore.PG.NTS/Extensions/NpgsqlNetTopologySuiteDbContextOptionsBuilderExtensions.cs1-30 src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs13-55
The plugin registers mappings for NetTopologySuite types through NpgsqlNetTopologySuiteTypeMappingSourcePlugin. It parses PostGIS store type names to determine the correct CLR type and metadata (SRID, Ordinates).
| NTS CLR Type | PostGIS Subtype Name | File Reference |
|---|---|---|
Point | POINT | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs24 |
LineString | LINESTRING | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs25 |
Polygon | POLYGON | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs26 |
MultiPoint | MULTIPOINT | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs27 |
MultiLineString | MULTILINESTRING | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs28 |
MultiPolygon | MULTIPOLYGON | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs29 |
GeometryCollection | GEOMETRYCOLLECTION | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs30 |
Geometry | GEOMETRY | src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs31 |
The NpgsqlGeometryTypeMapping<TGeometry> class handles the generation of SQL literals, including SRID prefixes (e.g., GEOMETRY 'SRID=4326;POINT(0 0)').
Sources: src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs20-36 src/EFCore.PG.NTS/Storage/Internal/NpgsqlGeometryTypeMapping.cs76-98
The provider can parse complex PostGIS store types using TryParseStoreTypeName. This allows it to extract:
geometry or geography type.Point, LineString).Sources: src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs117-182
The plugin provides three primary translation plugins that bridge the gap between .NET NTS calls and PostGIS functions:
NpgsqlNetTopologySuiteMethodCallTranslatorPlugin: Translates instance methods on Geometry and its subclasses.NpgsqlNetTopologySuiteMemberTranslatorPlugin: Translates property access (like Point.X or Geometry.Area).NpgsqlNetTopologySuiteAggregateMethodCallTranslatorPlugin: Translates LINQ aggregates like GeometryCombiner.Combine or ConvexHull.Create.| NTS Method | PostGIS Function / Operator | Source File |
|---|---|---|
Distance(other) | ST_Distance | src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMethodCallTranslatorPlugin.cs135 |
Intersects(other) | ST_Intersects | test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeographyTest.cs191 |
Buffer(distance) | ST_Buffer | test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeometryTest.cs71 |
Contains(other) | ST_Contains | test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeometryTest.cs132 |
Enumerable.ElementAt(x) | ST_GeometryN(collection, x + 1) | src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMethodCallTranslatorPlugin.cs93-99 |
| NTS Property | PostGIS Function | Source File |
|---|---|---|
Point.X | ST_X | src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMemberTranslatorPlugin.cs121 |
Point.Y | ST_Y | src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMemberTranslatorPlugin.cs122 |
Geometry.Area | ST_Area | test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeometryTest.cs27 |
Geometry.Centroid | ST_Centroid | test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeometryTest.cs93 |
NpgsqlNetTopologySuiteDbFunctionsExtensions provides access to PostGIS-specific features that don't have direct NTS equivalents:
| Extension Method | SQL Translation | Purpose |
|---|---|---|
Transform(geom, srid) | ST_Transform | Coordinate system conversion |
IntersectsBbox(g1, g2) | && operator | Bounding box intersection check |
DistanceKnn(g1, g2) | <-> operator | Index-assisted nearest-neighbor distance |
IsWithinDistance | ST_DWithin | Efficient distance check |
Sources: src/EFCore.PG.NTS/Extensions/NpgsqlNetTopologySuiteDbFunctionsExtensions.cs8-83 src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMethodCallTranslatorPlugin.cs104-141
Aggregate translations are handled by NpgsqlNetTopologySuiteAggregateMethodTranslator. It maps NTS utility classes to PostGIS aggregate functions:
GeometryCombiner.Combine maps to ST_Collect.ConvexHull.Create maps to ST_ConvexHull(ST_Collect(...)).EnvelopeCombiner.CombineAsGeometry maps to ST_Extent (with a cast to geometry).The following diagram illustrates how a LINQ query is processed by the spatial translators:
Sources: src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMethodCallTranslatorPlugin.cs73-102 src/EFCore.PG.NTS/Query/ExpressionTranslators/Internal/NpgsqlNetTopologySuiteMemberTranslatorPlugin.cs100-111
The provider includes extensive functional tests for both geometry and geography types.
SpatialQueryNpgsqlGeometryTest: Validates translations for standard geometry operations like ST_Area, ST_Buffer, and ST_Contains.SpatialQueryNpgsqlGeographyTest: Validates translations for geography-specific behavior, including spheroid distance calculations via ST_Distance(..., useSpheroid).Sources: test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeometryTest.cs10-41 test/EFCore.PG.FunctionalTests/Query/SpatialQueryNpgsqlGeographyTest.cs99-123
Refresh this wiki