Skip to content

Commit

Permalink
Update Spatial docs
Browse files Browse the repository at this point in the history
Fixes dotnet#1118, fixes dotnet#2352, fixes dotnet#2611, fixes dotnet#2674
  • Loading branch information
bricelam committed Oct 1, 2020
1 parent 6449d9e commit c104ad7
Show file tree
Hide file tree
Showing 14 changed files with 9,756 additions and 594 deletions.
300 changes: 27 additions & 273 deletions entity-framework/core/modeling/spatial.md

Large diffs are not rendered by default.

98 changes: 98 additions & 0 deletions entity-framework/core/providers/sql-server/spatial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: Microsoft SQL Server Database Provider - Spatial Data - EF Core
description: Using spatial data with the Entity Framework Core Microsoft SQL Server database provider
author: bricelam
ms.author: bricelam
ms.date: 09/29/2020
uid: core/providers/sql-server/spatial
---
# Spatial Data in the SQL Server EF Core Provider

This page includes additional information about using spatial data with the Microsoft SQL Server database provider. For general information about using spatial data in EF Core, see the main [Spatial Data](xref:core/modeling/spatial) documentation.

## Geography or geometry

By default, spatial properties are mapped to `geography` columns in SQL Server. To use `geometry`, [configure the column type](xref:core/modeling/entity-properties#column-data-types) in your model.

## Geography polygon rings

When using the `geography` column type, SQL Server imposes additional requirements on the exterior ring (or shell) and interior rings (or holes). The exterior ring must be oriented counterclockwise and the interior rings clockwise. NTS validates this before sending values to the database.

## FullGlobe

SQL Server has a non-standard geometry type to represent the full globe when using the `geography` column type. It also has a way to represent polygons based on the full globe (without an exterior ring). Neither of these are supported by NTS.

> [!WARNING]
> FullGlobe and polygons based on it aren't supported by NTS.
## Curves

As mentioned in the main [Spatial Data](xref:core/modeling/spatial) documentation, NetTopologySuite currently cannot represent curves. This means that you'll need to transform CircularString, CompoundCurve, and CurePolygon values using the [STCurveToLine](/sql/t-sql/spatial-geography/stcurvetoline-geography-data-type) method before using them in EF Core.

> [!WARNING]
> CircularString, CompoundCurve, and CurePolygon aren't supported by NTS.
## Translated Operations

This table shows which NTS members are translated into which SQL functions. Note that the translations vary depending on whether the column is of type geography or geometry.

.NET | SQL (geography) | SQL (geometry)
----------------------------------------- | ------------------------------------------------------------ | --------------
geometry.Area | @geometry.STArea() | @geometry.STArea()
geometry.AsBinary() | @geometry.STAsBinary() | @geometry.STAsBinary()
geometry.AsText() | @geometry.AsTextZM() | @geometry.AsTextZM()
geometry.Boundary | | @geometry.STBoundary()
geometry.Buffer(distance) | @geometry.STBuffer(@distance) | @geometry.STBuffer(@distance)
geometry.Centroid | | @geometry.STCentroid()
geometry.Contains(g) | @geometry.STContains(@g) | @geometry.STContains(@g)
geometry.ConvexHull() | @geometry.STConvexHull() | @geometry.STConvexHull()
geometry.Crosses(g) | | @geometry.STCrosses(@g)
geometry.Difference(other) | @geometry.STDifference(@other) | @geometry.STDifference(@other)
geometry.Dimension | @geometry.STDimension() | @geometry.STDimension()
geometry.Disjoint(g) | @geometry.STDisjoint(@g) | @geometry.STDisjoint(@g)
geometry.Distance(g) | @geometry.STDistance(@g) | @geometry.STDistance(@g)
geometry.Envelope | | @geometry.STEnvelope()
geometry.EqualsTopologically(g) | @geometry.STEquals(@g) | @geometry.STEquals(@g)
geometry.GeometryType | @geometry.STGeometryType() | @geometry.STGeometryType()
geometry.GetGeometryN(n) | @geometry.STGeometryN(@n + 1) | @geometry.STGeometryN(@n + 1)
geometry.InteriorPoint | | @geometry.STPointOnSurface()
geometry.Intersection(other) | @geometry.STIntersection(@other) | @geometry.STIntersection(@other)
geometry.Intersects(g) | @geometry.STIntersects(@g) | @geometry.STIntersects(@g)
geometry.IsEmpty | @geometry.STIsEmpty() | @geometry.STIsEmpty()
geometry.IsSimple | | @geometry.STIsSimple()
geometry.IsValid | @geometry.STIsValid() | @geometry.STIsValid()
geometry.IsWithinDistance(geom, distance) | @geometry.STDistance(@geom) <= @distance | @geometry.STDistance(@geom) <= @distance
geometry.Length | @geometry.STLength() | @geometry.STLength()
geometry.NumGeometries | @geometry.STNumGeometries() | @geometry.STNumGeometries()
geometry.NumPoints | @geometry.STNumPoints() | @geometry.STNumPoints()
geometry.OgcGeometryType | CASE @geometry.STGeometryType() WHEN N'Point' THEN 1 ... END | CASE @geometry.STGeometryType() WHEN N'Point' THEN 1 ... END
geometry.Overlaps(g) | @geometry.STOverlaps(@g) | @geometry.STOverlaps(@g)
geometry.PointOnSurface | | @geometry.STPointOnSurface()
geometry.Relate(g, intersectionPattern) | | @geometry.STRelate(@g, @intersectionPattern)
geometry.SRID | @geometry.STSrid | @geometry.STSrid
geometry.SymmetricDifference(other) | @geometry.STSymDifference(@other) | @geometry.STSymDifference(@other)
geometry.ToBinary() | @geometry.STAsBinary() | @geometry.STAsBinary()
geometry.ToText() | @geometry.AsTextZM() | @geometry.AsTextZM()
geometry.Touches(g) | | @geometry.STTouches(@g)
geometry.Union(other) | @geometry.STUnion(@other) | @geometry.STUnion(@other)
geometry.Within(g) | @geometry.STWithin(@g) | @geometry.STWithin(@g)
geometryCollection[i] | @geometryCollection.STGeometryN(@i + 1) | @geometryCollection.STGeometryN(@i + 1)
geometryCollection.Count | @geometryCollection.STNumGeometries() | @geometryCollection.STNumGeometries()
lineString.Count | @lineString.STNumPoints() | @lineString.STNumPoints()
lineString.EndPoint | @lineString.STEndPoint() | @lineString.STEndPoint()
lineString.GetPointN(n) | @lineString.STPointN(@n + 1) | @lineString.STPointN(@n + 1)
lineString.IsClosed | @lineString.STIsClosed() | @lineString.STIsClosed()
lineString.IsRing | | @lineString.IsRing()
lineString.StartPoint | @lineString.STStartPoint() | @lineString.STStartPoint()
multiLineString.IsClosed | @multiLineString.STIsClosed() | @multiLineString.STIsClosed()
point.M | @point.M | @point.M
point.X | @point.Long | @point.STX
point.Y | @point.Lat | @point.STY
point.Z | @point.Z | @point.Z
polygon.ExteriorRing | @polygon.RingN(1) | @polygon.STExteriorRing()
polygon.GetInteriorRingN(n) | @polygon.RingN(@n + 2) | @polygon.STInteriorRingN(@n + 1)
polygon.NumInteriorRings | @polygon.NumRings() - 1 | @polygon.STNumInteriorRing()

## Additional resources

* [Spatial Data in SQL Server](/sql/relational-databases/spatial/spatial-data-sql-server)
133 changes: 133 additions & 0 deletions entity-framework/core/providers/sqlite/spatial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
title: SQLite Database Provider - Spatial Data - EF Core
description: Using spatial data with the Entity Framework Core SQLite database provider
author: bricelam
ms.author: bricelam
ms.date: 09/29/2020
uid: core/providers/sqlite/spatial
---
# Spatial Data in the SQLite EF Core Provider

This page includes additional information about using spatial data with the SQLite database provider. For general information about using spatial data in EF Core, see the main [Spatial Data](xref:core/modeling/spatial) documentation.

## Installing SpatiaLite

On Windows, the native mod_spatialite library is distributed as a NuGet package dependency. Other platforms need to install it separately. This is typically done using a software package manager. For example, you can use APT on Debian and Ubuntu; and Homebrew on MacOS.

``` sh
# Debian/Ubuntu
apt-get install libsqlite3-mod-spatialite

# macOS
brew install libspatialite
```

Unfortunately, newer versions of PROJ (a dependency of SpatiaLite) are incompatible with EF's default [SQLitePCLRaw bundle](/dotnet/standard/data/sqlite/custom-versions#bundles). You can work around this by using the system SQLite library instead.

```xml
<ItemGroup>
<!-- Use bundle_sqlite3 instead with SpatiaLite on macOS and Linux -->
<!--<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0" />-->
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="3.1.0" />
<PackageReference Include="SQLitePCLRaw.bundle_sqlite3" Version="2.0.4" />

<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="3.1.0" />
</ItemGroup>
```

On **macOS**, you'll also need set an environment variable before running your app so it uses Homebrew's version of SQLite. In Visual Studio for Mac, you can set this under **Project > Project Options > Run > Configurations > Default**

```sh
DYLD_LIBRARY_PATH=/usr/local/opt/sqlite/lib
```

## Configuring SRID

In SpatiaLite, columns need to specify an SRID per column. The default SRID is `0`. Specify a different SRID using the ForSqliteHasSrid method.

``` csharp
modelBuilder.Entity<City>().Property(c => c.Location)
.ForSqliteHasSrid(4326);
```

> [!NOTE]
> 4326 refers to WGS 84, a standard used in GPS and other geographic systems.
## Dimension

The default dimension (or ordinates) of a column is X and Y. To enable additional ordinates like Z or M, configure the column type.

``` csharp
modelBuilder.Entity<City>().Property(c => c.Location)
.HasColumnType("POINTZ");
```

## Translated Operations

This table shows which NTS members are translated into which SQL functions.

.NET | SQL
------------------------------------------- | ---
geometry.Area | Area(@geometry)
geometry.AsBinary() | AsBinary(@geometry)
geometry.AsText() | AsText(@geometry)
geometry.Boundary | Boundary(@geometry)
geometry.Buffer(distance) | Buffer(@geometry, @distance)
geometry.Buffer(distance, quadrantSegments) | Buffer(@geometry, @distance, @quadrantSegments)
geometry.Centroid | Centroid(@geometry)
geometry.Contains(g) | Contains(@geometry, @g)
geometry.ConvexHull() | ConvexHull(@geometry)
geometry.CoveredBy(g) | CoveredBy(@geometry, @g)
geometry.Covers(g) | Covers(@geometry, @g)
geometry.Crosses(g) | Crosses(@geometry, @g)
geometry.Difference(other) | Difference(@geometry, @other)
geometry.Dimension | Dimension(@geometry)
geometry.Disjoint(g) | Disjoint(@geometry, @g)
geometry.Distance(g) | Distance(@geometry, @g)
geometry.Envelope | Envelope(@geometry)
geometry.EqualsTopologically(g) | Equals(@geometry, @g)
geometry.GeometryType | GeometryType(@geometry)
geometry.GetGeometryN(n) | GeometryN(@geometry, @n + 1)
geometry.InteriorPoint | PointOnSurface(@geometry)
geometry.Intersection(other) | Intersection(@geometry, @other)
geometry.Intersects(g) | Intersects(@geometry, @g)
geometry.IsEmpty | IsEmpty(@geometry)
geometry.IsSimple | IsSimple(@geometry)
geometry.IsValid | IsValid(@geometry)
geometry.IsWithinDistance(geom, distance) | Distance(@geometry, @geom) <= @distance
geometry.Length | GLength(@geometry)
geometry.NumGeometries | NumGeometries(@geometry)
geometry.NumPoints | NumPoints(@geometry)
geometry.OgcGeometryType | CASE GeometryType(@geometry) WHEN 'POINT' THEN 1 ... END
geometry.Overlaps(g) | Overlaps(@geometry, @g)
geometry.PointOnSurface | PointOnSurface(@geometry)
geometry.Relate(g, intersectionPattern) | Relate(@geometry, @g, @intersectionPattern)
geometry.Reverse() | ST_Reverse(@geometry)
geometry.SRID | SRID(@geometry)
geometry.SymmetricDifference(other) | SymDifference(@geometry, @other)
geometry.ToBinary() | AsBinary(@geometry)
geometry.ToText() | AsText(@geometry)
geometry.Touches(g) | Touches(@geometry, @g)
geometry.Union() | UnaryUnion(@geometry)
geometry.Union(other) | GUnion(@geometry, @other)
geometry.Within(g) | Within(@geometry, @g)
geometryCollection[i] | GeometryN(@geometryCollection, @i + 1)
geometryCollection.Count | NumGeometries(@geometryCollection)
lineString.Count | NumPoints(@lineString)
lineString.EndPoint | EndPoint(@lineString)
lineString.GetPointN(n) | PointN(@lineString, @n + 1)
lineString.IsClosed | IsClosed(@lineString)
lineString.IsRing | IsRing(@lineString)
lineString.StartPoint | StartPoint(@lineString)
multiLineString.IsClosed | IsClosed(@multiLineString)
point.M | M(@point)
point.X | X(@point)
point.Y | Y(@point)
point.Z | Z(@point)
polygon.ExteriorRing | ExteriorRing(@polygon)
polygon.GetInteriorRingN(n) | InteriorRingN(@polygon, @n + 1)
polygon.NumInteriorRings | NumInteriorRing(@polygon)

## Additional resources

* [SpatiaLite Homepage](https://www.gaia-gis.it/fossil/libspatialite)
Loading

0 comments on commit c104ad7

Please sign in to comment.