Spatial Data and NetTopologySuite

The Oracle database can store spatial data that represents physical locations and object shapes. ODP.NET can operate on Oracle spatial data natively.

EF Core maps to spatial data types with the NetTopologySuite (NTS) spatial library. Starting with Oracle EF Core 10, Oracle database SDO_GEOMETRY spatial data types can be accessed and mapped using the Oracle EF Core NTS library.

This library enables Oracle spatial columns to be mapped to .NET geometry types, such as Point and Polygon. LINQ statements for the Oracle database can include spatial logic, such as distance and intersection. EF Core apps can now use a standard way to query, insert, update, and delete Oracle database spatial data.

See Also:

Setup

This Oracle spatial library is available in the Oracle.EntityFrameworkCore.NetTopologySuite package on NuGet Gallery. The NuGet package manager automatically retrieves other NTS packages needed to support Oracle EF Core spatial types.

To setup an app that uses Oracle spatial data in EF Core, follow these steps:

  1. Add the Oracle.EntityFrameworkCore.NetTopologySuite package to your .NET project.

  2. Use DbContext to enable the library. The extension method, UseNetTopologySuite(), configures the spatial provider settings, including the spatial tolerance level which controls the allowable geometric calculation error margin. For example:

services.AddDbContext<MyContext>(options =>
    options.UseOracle("<CONNECTION STRING>",
        o => o.UseNetTopologySuite(tolerance: 0.01)));
  1. In the entity model, define the spatial class. For example:
public class MySpatialEntity
{
    public int Id { get; set; }

   // NetTopologySuite.Geometries.Point
    public Point Location { get; set; }
}
  1. Write a LINQ for the spatial data, such as
Point myPoint = new Point(10, 20);
var nearby = context.MySpatialEntities
    .Where(e => e.Location.IsWithinDistance(myPoint, 1000))
    .ToList();

Features

Oracle EF Core supports the following features:

Note: Oracle Spatial supports a superset of features not available or with limited features in NTS, such as curved geometry. EF Core spatial support is limited to NTS capabilities.

Oracle NetTopologySuite Members

Table 6 NetTopologySuite Methods and Oracle Spatial Functions Mapping

NetTopologySuite Methods Oracle Spatial Functions
EnvelopeCombiner.CombineAsGeometry(geom[]) SDO_AGGR_MBR
Geometry.AsBinary() SDO_UTIL.TO_WKBGEOMETRY
Geometry.AsText() SDO_UTIL.TO_WKTGEOMETRY
Geometry.Buffer(distance) SDO_GEOM.SDO_BUFFER
Geometry.Contains(geom) SDO_CONTAINS
Geometry.ConvexHull() SDO_GEOM.SDO_CONVEXHULL
Geometry.CoveredBy(geom) SDO_RELATE
Geometry.Covers(geom) SDO_RELATE
Geometry.Crosses(geom) SDO_RELATE
Geometry.Disjoint(geom) SDO_RELATE
Geometry.Difference(geom) SDO_GEOM.DIFFERENCE
Geometry.Distance(geom) SDO_GEOM.SDO_DISTANCE
Geometry.EqualsExact(geom) SDO_RELATE
Geometry.EqualsTopologically(geom) SDO_RELATE
Geometry.GetGeometryN(n) SDO_UTIL.EXTRACT
Geometry.Intersection(geom) SDO_GEOM.SDO_INTERSECTION
Geometry.Intersects(geom) SDO_RELATE
Geometry.IsWithinDistance(geom, dist) SDO_WITHIN_DISTANCE
Geometry.Overlaps(geom) SDO_RELATE
Geometry.Relate(geom, pattern). Instead of the DE-9IM pattern, Oracle uses relevant mask words SDO_RELATE
Geometry.Reverse() for LineString only and requires Oracle Database 23ai or higher. SDO_UTIL.REVERSE_LINESTRING
Geometry.SymmetricDifference(geom) SDO_GEOM.SDO_XOR
Geometry.ToBinary() SDO_UTIL.TO_WKBGEOMETRY
Geometry.ToText() SDO_UTIL.TO_WKTGEOMETRY
Geometry.Touches(geom) SDO_RELATE
Geometry.Within(geom) SDO_CONTAINS
Geometry.Union() SDO_GEOM.SDO_SELF_UNION
Geometry.Union(geom) SDO_GEOM.SDO_UNION
GeometryCombiner.Combine(geom[]) SDO_AGGR_UNION
ConvexHull.Create(geom[]) SDO_AGGR_CONVEXHULL
UnaryUnionOp.Union(geom[]) SDO_AGGR_UNION

Table 7 NetTopologySuite Properties and Oracle Spatial Functions Mapping

NetTopologySuite Properties Oracle Spatial Functions
Geometry.Area SDO_GEOM.SDO_AREA
Geometry.Centroid SDO_GEOM.SDO_CENTROID
Geometry.Envelope SDO_GEOM.SDO_MBR
Geometry.GeometryType CASE on SDO_GTYPE
Geometry.InteriorPoint SDO_GEOM.SDO_POINTONSURFACE
Geometry.IsEmpty Composite null checks on SDO_GEOMETRY fields
Geometry.IsSimple SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT
Geometry.IsValid SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT
Geometry.Length SDO_GEOM.SDO_LENGTH
Geometry.NumGeometries SDO_UTIL.GETNUMELEM
Geometry.NumPoints SDO_UTIL.GETNUMVERTICES
Geometry.OgcGeometryType CASE on SDO_GTYPE
Geometry.PointOnSurface SDO_GEOM.SDO_POINTONSURFACE
Geometry.SRID SDO_SRID(field)
GeometryCollection.Count SDO_UTIL.GETNUMELEM
LineString.Count SDO_UTIL.GETNUMVERTICES
LineString.EndPoint SDO_LRS.GEOM_SEGMENT_END_PT
LineString.IsClosed SDO_EQUAL(SDO_LRS.GEOM_SEGMENT_START_PT and SDO_LRS.GEOM_SEGMENT_END_PT)
LineString.IsRing SDO_EQUAL(SDO_LRS.GEOM_SEGMENT_START_PT, SDO_LRS.GEOM_SEGMENT_END_PT), and SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT
LineString.StartPoint SDO_LRS.GEOM_SEGMENT_START_PT
Point.X SDO_POINT.X
Point.Y SDO_POINT.Y
Point.Z SDO_POINT.Z
Polygon.ExteriorRing SDO_UTIL.POLYGONTOLINE and SDO_UTIL.EXTRACT(geom, 1, 0)
Polygon.NumInteriorRings SDO_UTIL.GETNUMRINGS - 1

If a NTS member requires a specific minimum Oracle database version, such as Geometry.Reverse(), then set the [UseOracleSQLCompatibility(enum version)](EFCoreAPI.html#GUID-41786CF0-11E3-4AD2-8ED1-3D31D5FE2082) extension method enum value to a supported database version.

Limitations and Workarounds