|
1 | | ---- |
2 | | -title: SQLite Database Provider - Spatial Data - EF Core |
3 | | -description: Using spatial data with the Entity Framework Core SQLite database provider |
4 | | -author: SamMonoRT |
5 | | -ms.date: 10/02/2020 |
6 | | -uid: core/providers/sqlite/spatial |
7 | | ---- |
8 | | -# Spatial Data in the SQLite EF Core Provider |
9 | | - |
10 | | -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. |
11 | | - |
12 | | -## Installing SpatiaLite |
13 | | - |
14 | | -On Windows, the native `mod_spatialite` library is distributed as a [NuGet package](https://www.nuget.org/packages/mod_spatialite) 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. |
15 | | - |
16 | | -```bash |
17 | | -# Debian/Ubuntu |
18 | | -apt-get install libsqlite3-mod-spatialite |
19 | | - |
20 | | -# macOS |
21 | | -brew install libspatialite |
22 | | -``` |
23 | | - |
24 | | -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. |
25 | | - |
26 | | -```xml |
27 | | -<ItemGroup> |
28 | | - <!-- Use bundle_sqlite3 instead with SpatiaLite on macOS and Linux --> |
29 | | - <!--<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0" />--> |
30 | | - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="3.1.0" /> |
31 | | - <PackageReference Include="SQLitePCLRaw.bundle_sqlite3" Version="2.0.4" /> |
32 | | - |
33 | | - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="3.1.0" /> |
34 | | -</ItemGroup> |
35 | | -``` |
36 | | - |
37 | | -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** |
38 | | - |
39 | | -```bash |
40 | | -DYLD_LIBRARY_PATH=/usr/local/opt/sqlite/lib |
41 | | -``` |
42 | | - |
43 | | -## Configuring SRID |
44 | | - |
45 | | -In SpatiaLite, columns need to specify an SRID per column. The default SRID is `0`. Specify a different SRID using the HasSrid method. |
46 | | - |
47 | | -```csharp |
48 | | -modelBuilder.Entity<City>().Property(c => c.Location) |
49 | | - .HasSrid(4326); |
50 | | -``` |
51 | | - |
52 | | -> [!NOTE] |
53 | | -> 4326 refers to WGS 84, a standard used in GPS and other geographic systems. |
54 | | -
|
55 | | -## Dimension |
56 | | - |
57 | | -The default dimension (or ordinates) of a column is X and Y. To enable additional ordinates like Z or M, configure the column type. |
58 | | - |
59 | | -```csharp |
60 | | -modelBuilder.Entity<City>().Property(c => c.Location) |
61 | | - .HasColumnType("POINTZ"); |
62 | | -``` |
63 | | - |
64 | | -## Spatial function mappings |
65 | | - |
66 | | -This table shows which [NetTopologySuite](https://nettopologysuite.github.io/NetTopologySuite/) (NTS) members are translated into which SQL functions. |
67 | | - |
68 | | -.NET | SQL |
69 | | -------------------------------------------- | --- |
70 | | -geometry.Area | Area(@geometry) |
71 | | -geometry.AsBinary() | AsBinary(@geometry) |
72 | | -geometry.AsText() | AsText(@geometry) |
73 | | -geometry.Boundary | Boundary(@geometry) |
74 | | -geometry.Buffer(distance) | Buffer(@geometry, @distance) |
75 | | -geometry.Buffer(distance, quadrantSegments) | Buffer(@geometry, @distance, @quadrantSegments) |
76 | | -geometry.Centroid | Centroid(@geometry) |
77 | | -geometry.Contains(g) | Contains(@geometry, @g) |
78 | | -geometry.ConvexHull() | ConvexHull(@geometry) |
79 | | -geometry.CoveredBy(g) | CoveredBy(@geometry, @g) |
80 | | -geometry.Covers(g) | Covers(@geometry, @g) |
81 | | -geometry.Crosses(g) | Crosses(@geometry, @g) |
82 | | -geometry.Difference(other) | Difference(@geometry, @other) |
83 | | -geometry.Dimension | Dimension(@geometry) |
84 | | -geometry.Disjoint(g) | Disjoint(@geometry, @g) |
85 | | -geometry.Distance(g) | Distance(@geometry, @g) |
86 | | -geometry.Envelope | Envelope(@geometry) |
87 | | -geometry.EqualsTopologically(g) | Equals(@geometry, @g) |
88 | | -geometry.GeometryType | GeometryType(@geometry) |
89 | | -geometry.GetGeometryN(n) | GeometryN(@geometry, @n + 1) |
90 | | -geometry.InteriorPoint | PointOnSurface(@geometry) |
91 | | -geometry.Intersection(other) | Intersection(@geometry, @other) |
92 | | -geometry.Intersects(g) | Intersects(@geometry, @g) |
93 | | -geometry.IsEmpty | IsEmpty(@geometry) |
94 | | -geometry.IsSimple | IsSimple(@geometry) |
95 | | -geometry.IsValid | IsValid(@geometry) |
96 | | -geometry.IsWithinDistance(geom, distance) | Distance(@geometry, @geom) <= @distance |
97 | | -geometry.Length | GLength(@geometry) |
98 | | -geometry.NumGeometries | NumGeometries(@geometry) |
99 | | -geometry.NumPoints | NumPoints(@geometry) |
100 | | -geometry.OgcGeometryType | CASE GeometryType(@geometry) WHEN 'POINT' THEN 1 ... END |
101 | | -geometry.Overlaps(g) | Overlaps(@geometry, @g) |
102 | | -geometry.PointOnSurface | PointOnSurface(@geometry) |
103 | | -geometry.Relate(g, intersectionPattern) | Relate(@geometry, @g, @intersectionPattern) |
104 | | -geometry.Reverse() | ST_Reverse(@geometry) |
105 | | -geometry.SRID | SRID(@geometry) |
106 | | -geometry.SymmetricDifference(other) | SymDifference(@geometry, @other) |
107 | | -geometry.ToBinary() | AsBinary(@geometry) |
108 | | -geometry.ToText() | AsText(@geometry) |
109 | | -geometry.Touches(g) | Touches(@geometry, @g) |
110 | | -geometry.Union() | UnaryUnion(@geometry) |
111 | | -geometry.Union(other) | GUnion(@geometry, @other) |
112 | | -geometry.Within(g) | Within(@geometry, @g) |
113 | | -geometryCollection[i] | GeometryN(@geometryCollection, @i + 1) |
114 | | -geometryCollection.Count | NumGeometries(@geometryCollection) |
115 | | -lineString.Count | NumPoints(@lineString) |
116 | | -lineString.EndPoint | EndPoint(@lineString) |
117 | | -lineString.GetPointN(n) | PointN(@lineString, @n + 1) |
118 | | -lineString.IsClosed | IsClosed(@lineString) |
119 | | -lineString.IsRing | IsRing(@lineString) |
120 | | -lineString.StartPoint | StartPoint(@lineString) |
121 | | -multiLineString.IsClosed | IsClosed(@multiLineString) |
122 | | -point.M | M(@point) |
123 | | -point.X | X(@point) |
124 | | -point.Y | Y(@point) |
125 | | -point.Z | Z(@point) |
126 | | -polygon.ExteriorRing | ExteriorRing(@polygon) |
127 | | -polygon.GetInteriorRingN(n) | InteriorRingN(@polygon, @n + 1) |
128 | | -polygon.NumInteriorRings | NumInteriorRing(@polygon) |
129 | | - |
130 | | -### Aggregate functions |
131 | | - |
132 | | -.NET | SQL | Added in |
133 | | ------------------------------------------------------------------ | ----------------------------- | -------- |
134 | | -GeometryCombiner.Combine(group.Select(x => x.Property)) | Collect(Property) | EF Core 7.0 |
135 | | -ConvexHull.Create(group.Select(x => x.Property)) | ConvexHull(Collect(Property)) | EF Core 7.0 |
136 | | -UnaryUnionOp.Union(group.Select(x => x.Property)) | GUnion(Property) | EF Core 7.0 |
137 | | -EnvelopeCombiner.CombineAsGeometry(group.Select(x => x.Property)) | Extent(Property) | EF Core 7.0 |
138 | | - |
139 | | -## Additional resources |
140 | | - |
141 | | -* [SpatiaLite Homepage](https://www.gaia-gis.it/fossil/libspatialite) |
142 | | -* [NetTopologySuite API Documentation](https://nettopologysuite.github.io/NetTopologySuite/api/NetTopologySuite.html) |
| 1 | +--- |
| 2 | +title: SQLite Database Provider - Spatial Data - EF Core |
| 3 | +description: Using spatial data with the Entity Framework Core SQLite database provider |
| 4 | +author: SamMonoRT |
| 5 | +ms.date: 03/27/2026 |
| 6 | +uid: core/providers/sqlite/spatial |
| 7 | +--- |
| 8 | +# Spatial Data in the SQLite EF Core Provider |
| 9 | + |
| 10 | +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. |
| 11 | + |
| 12 | +## Installing SpatiaLite |
| 13 | + |
| 14 | +On Windows, the native `mod_spatialite` library is distributed as a [NuGet package](https://www.nuget.org/packages/mod_spatialite) 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. |
| 15 | + |
| 16 | +```bash |
| 17 | +# Debian/Ubuntu |
| 18 | +apt-get install libsqlite3-mod-spatialite |
| 19 | + |
| 20 | +# macOS |
| 21 | +brew install libspatialite |
| 22 | +``` |
| 23 | + |
| 24 | +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. |
| 25 | + |
| 26 | +> [!IMPORTANT] |
| 27 | +> Don't use `Microsoft.EntityFrameworkCore.Sqlite` or `Microsoft.Data.Sqlite` with SpatiaLite on macOS and Linux. Both packages pull in `SQLitePCLRaw.bundle_e_sqlite3` by default—a bundled version of SQLite that is incompatible with system-installed Sqlite. Using it may result in a silent crash at run time. Use `Microsoft.EntityFrameworkCore.Sqlite.Core` or `Microsoft.Data.Sqlite.Core` instead, together with the system SQLite provider as shown below. |
| 28 | +
|
| 29 | +Replace `Microsoft.EntityFrameworkCore.Sqlite` with `Microsoft.EntityFrameworkCore.Sqlite.Core` and reference the `SQLitePCLRaw.provider.sqlite3` package to use the system SQLite library: |
| 30 | + |
| 31 | +```xml |
| 32 | +<ItemGroup> |
| 33 | + <!-- Use Sqlite.Core with the system SQLite provider instead of Microsoft.EntityFrameworkCore.Sqlite --> |
| 34 | + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="10.0.0" /> |
| 35 | + <PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.10" /> |
| 36 | + |
| 37 | + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="10.0.0" /> |
| 38 | +</ItemGroup> |
| 39 | +``` |
| 40 | + |
| 41 | +> [!NOTE] |
| 42 | +> Starting with EF Core 11 (SQLitePCLRaw 3.0), replace the `SQLitePCLRaw.provider.sqlite3` version with `3.x.x`. See the [breaking changes](xref:core/what-is-new/ef-core-11.0/breaking-changes#sqlite-bundles-removed) for details. |
| 43 | +
|
| 44 | +Then add explicit initialization before using SQLite: |
| 45 | + |
| 46 | +```csharp |
| 47 | +SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); |
| 48 | +``` |
| 49 | + |
| 50 | +On **macOS**, you'll also need to set an environment variable before running your app so it uses Homebrew's version of SQLite: |
| 51 | + |
| 52 | +```bash |
| 53 | +DYLD_LIBRARY_PATH="$(brew --prefix sqlite)/lib" |
| 54 | +``` |
| 55 | + |
| 56 | +## Configuring SRID |
| 57 | + |
| 58 | +In SpatiaLite, columns need to specify an SRID per column. The default SRID is `0`. Specify a different SRID using the HasSrid method. |
| 59 | + |
| 60 | +```csharp |
| 61 | +modelBuilder.Entity<City>().Property(c => c.Location) |
| 62 | + .HasSrid(4326); |
| 63 | +``` |
| 64 | + |
| 65 | +> [!NOTE] |
| 66 | +> 4326 refers to WGS 84, a standard used in GPS and other geographic systems. |
| 67 | +
|
| 68 | +## Dimension |
| 69 | + |
| 70 | +The default dimension (or ordinates) of a column is X and Y. To enable additional ordinates like Z or M, configure the column type. |
| 71 | + |
| 72 | +```csharp |
| 73 | +modelBuilder.Entity<City>().Property(c => c.Location) |
| 74 | + .HasColumnType("POINTZ"); |
| 75 | +``` |
| 76 | + |
| 77 | +## Spatial function mappings |
| 78 | + |
| 79 | +This table shows which [NetTopologySuite](https://nettopologysuite.github.io/NetTopologySuite/) (NTS) members are translated into which SQL functions. |
| 80 | + |
| 81 | +.NET | SQL |
| 82 | +------------------------------------------- | --- |
| 83 | +geometry.Area | Area(@geometry) |
| 84 | +geometry.AsBinary() | AsBinary(@geometry) |
| 85 | +geometry.AsText() | AsText(@geometry) |
| 86 | +geometry.Boundary | Boundary(@geometry) |
| 87 | +geometry.Buffer(distance) | Buffer(@geometry, @distance) |
| 88 | +geometry.Buffer(distance, quadrantSegments) | Buffer(@geometry, @distance, @quadrantSegments) |
| 89 | +geometry.Centroid | Centroid(@geometry) |
| 90 | +geometry.Contains(g) | Contains(@geometry, @g) |
| 91 | +geometry.ConvexHull() | ConvexHull(@geometry) |
| 92 | +geometry.CoveredBy(g) | CoveredBy(@geometry, @g) |
| 93 | +geometry.Covers(g) | Covers(@geometry, @g) |
| 94 | +geometry.Crosses(g) | Crosses(@geometry, @g) |
| 95 | +geometry.Difference(other) | Difference(@geometry, @other) |
| 96 | +geometry.Dimension | Dimension(@geometry) |
| 97 | +geometry.Disjoint(g) | Disjoint(@geometry, @g) |
| 98 | +geometry.Distance(g) | Distance(@geometry, @g) |
| 99 | +geometry.Envelope | Envelope(@geometry) |
| 100 | +geometry.EqualsTopologically(g) | Equals(@geometry, @g) |
| 101 | +geometry.GeometryType | GeometryType(@geometry) |
| 102 | +geometry.GetGeometryN(n) | GeometryN(@geometry, @n + 1) |
| 103 | +geometry.InteriorPoint | PointOnSurface(@geometry) |
| 104 | +geometry.Intersection(other) | Intersection(@geometry, @other) |
| 105 | +geometry.Intersects(g) | Intersects(@geometry, @g) |
| 106 | +geometry.IsEmpty | IsEmpty(@geometry) |
| 107 | +geometry.IsSimple | IsSimple(@geometry) |
| 108 | +geometry.IsValid | IsValid(@geometry) |
| 109 | +geometry.IsWithinDistance(geom, distance) | Distance(@geometry, @geom) <= @distance |
| 110 | +geometry.Length | GLength(@geometry) |
| 111 | +geometry.NumGeometries | NumGeometries(@geometry) |
| 112 | +geometry.NumPoints | NumPoints(@geometry) |
| 113 | +geometry.OgcGeometryType | CASE GeometryType(@geometry) WHEN 'POINT' THEN 1 ... END |
| 114 | +geometry.Overlaps(g) | Overlaps(@geometry, @g) |
| 115 | +geometry.PointOnSurface | PointOnSurface(@geometry) |
| 116 | +geometry.Relate(g, intersectionPattern) | Relate(@geometry, @g, @intersectionPattern) |
| 117 | +geometry.Reverse() | ST_Reverse(@geometry) |
| 118 | +geometry.SRID | SRID(@geometry) |
| 119 | +geometry.SymmetricDifference(other) | SymDifference(@geometry, @other) |
| 120 | +geometry.ToBinary() | AsBinary(@geometry) |
| 121 | +geometry.ToText() | AsText(@geometry) |
| 122 | +geometry.Touches(g) | Touches(@geometry, @g) |
| 123 | +geometry.Union() | UnaryUnion(@geometry) |
| 124 | +geometry.Union(other) | GUnion(@geometry, @other) |
| 125 | +geometry.Within(g) | Within(@geometry, @g) |
| 126 | +geometryCollection[i] | GeometryN(@geometryCollection, @i + 1) |
| 127 | +geometryCollection.Count | NumGeometries(@geometryCollection) |
| 128 | +lineString.Count | NumPoints(@lineString) |
| 129 | +lineString.EndPoint | EndPoint(@lineString) |
| 130 | +lineString.GetPointN(n) | PointN(@lineString, @n + 1) |
| 131 | +lineString.IsClosed | IsClosed(@lineString) |
| 132 | +lineString.IsRing | IsRing(@lineString) |
| 133 | +lineString.StartPoint | StartPoint(@lineString) |
| 134 | +multiLineString.IsClosed | IsClosed(@multiLineString) |
| 135 | +point.M | M(@point) |
| 136 | +point.X | X(@point) |
| 137 | +point.Y | Y(@point) |
| 138 | +point.Z | Z(@point) |
| 139 | +polygon.ExteriorRing | ExteriorRing(@polygon) |
| 140 | +polygon.GetInteriorRingN(n) | InteriorRingN(@polygon, @n + 1) |
| 141 | +polygon.NumInteriorRings | NumInteriorRing(@polygon) |
| 142 | + |
| 143 | +### Aggregate functions |
| 144 | + |
| 145 | +.NET | SQL | Added in |
| 146 | +----------------------------------------------------------------- | ----------------------------- | -------- |
| 147 | +GeometryCombiner.Combine(group.Select(x => x.Property)) | Collect(Property) | EF Core 7.0 |
| 148 | +ConvexHull.Create(group.Select(x => x.Property)) | ConvexHull(Collect(Property)) | EF Core 7.0 |
| 149 | +UnaryUnionOp.Union(group.Select(x => x.Property)) | GUnion(Property) | EF Core 7.0 |
| 150 | +EnvelopeCombiner.CombineAsGeometry(group.Select(x => x.Property)) | Extent(Property) | EF Core 7.0 |
| 151 | + |
| 152 | +## Additional resources |
| 153 | + |
| 154 | +* [SpatiaLite Homepage](https://www.gaia-gis.it/fossil/libspatialite) |
| 155 | +* [NetTopologySuite API Documentation](https://nettopologysuite.github.io/NetTopologySuite/api/NetTopologySuite.html) |
0 commit comments