-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Spatial docs #2723
Update Spatial docs #2723
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
--- | ||
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: 10/02/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. [NetTopologySuite](https://nettopologysuite.github.io/NetTopologySuite/) (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, NTS 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) | ||
* [NetTopologySuite Docs](https://nettopologysuite.github.io/NetTopologySuite/) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
--- | ||
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: 10/02/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 [NetTopologySuite](https://nettopologysuite.github.io/NetTopologySuite/) (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) | ||
* [NetTopologySuite Docs](https://nettopologysuite.github.io/NetTopologySuite/) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -233,6 +233,9 @@ | |
href: core/providers/sql-server/indexes.md | ||
- name: Memory-optimized tables | ||
href: core/providers/sql-server/memory-optimized-tables.md | ||
- name: Spatial data | ||
displayName: GIS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we leave spatial data as the display name? Am just not sure everyone knows the name GIS. Not sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add Spatial Data too for localization. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
href: core/providers/sql-server/spatial.md | ||
- name: Specify Azure SQL Database options | ||
href: core/providers/sql-server/azure-sql-database.md | ||
- name: SQLite | ||
|
@@ -241,6 +244,9 @@ | |
href: core/providers/sqlite/index.md | ||
- name: SQLite limitations | ||
href: core/providers/sqlite/limitations.md | ||
- name: Spatial data | ||
displayName: GIS | ||
href: core/providers/sqlite/spatial.md | ||
- name: Cosmos | ||
items: | ||
- name: Overview | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a lower-level heading?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so, it's not really related to choosing between geometry or geography