Summary#
A Geography is a GeoJSON geometry: a point, a line, a polygon, or a collection of them, in longitude/latitude.
Declare it on an entity, build one with Geography.Point, or read one from text with Geography.Parse.
entity Store {
[Required] string Name;
Geography Location;
}
var here = Geography.Point(18.07, 59.33); // LONGITUDE first — Stockholm
var area = Geography.Parse(polygonGeoJson); // throws if it is not a valid geometrySignature#
Geography Geography.Point(double longitude, double latitude)
Geography Geography.Parse(string geoJson)Description#
Longitude comes first#
GeoJSON orders a position [longitude, latitude], and so does Geography.Point. The opposite order is the most
common mistake anyone makes with GeoJSON, and a swapped Stockholm is a perfectly valid-looking point in the wrong
country — so a longitude outside ±180 or a latitude outside ±90 is refused, and the message tells you to swap it.
That catches the mistake for most of the planet.
One geometry, one text#
Two spellings of the same geometry — keys in another order, 18.0 for 18, extra spaces — are the same
Geography. Every value is kept in one canonical form, so == compares places rather than formatting, and a value
read back from the database equals the one you stored.
Geography.Parse("{ \"coordinates\": [18.0, 59.330], \"type\": \"Point\" }")
== Geography.Point(18, 59.33) // true — the same point, spelled two waysConvert.ToString(g) gives you that canonical GeoJSON text, ready to hand to a map.
What is refused, and why#
| you pass | why it is refused |
|---|---|
a Feature or FeatureCollection | a geography is the geometry; a feature carries properties it has nowhere to keep. Pass feature.geometry. |
a geometry with a crs | GeoJSON is WGS84 longitude/latitude by definition. Coordinates in another system would be read as degrees and land in the wrong place — reproject first. |
| any other extra member | it would be dropped without a word. (bbox is the exception: it is derived from the coordinates, so nothing is lost.) |
| a polygon ring that does not end where it starts, or has fewer than 4 positions | not a closed shape |
| a line with one position | not a line |
Where it comes from#
A browser map library emits and consumes GeoJSON directly, and so do the warehouses — Snowflake and Databricks both
return a spatial column as GeoJSON (ST_ASGEOJSON). A Geography parameter on a function accepts the geometry as
a JSON object or as its text, so a map click and a warehouse row arrive the same way.
It is the same value on both sides#
Geography.Point and Geography.Parse give the same text in a server function and in a browser action, number for
number. Both runtimes are held to one shared table of cases — including the numbers where .NET's and JavaScript's
default formatting disagree.
Examples#
// Record where an order was delivered, from a map click in the browser.
entity Delivery {
[Required] string Reference;
Geography DroppedAt;
}
void Deliver(Delivery d, double longitude, double latitude) {
d.DroppedAt = Geography.Point(longitude, latitude);
}See also#
- DateTimeOffset — the other type added for warehouse columns: an instant with its offset
- bigdecimal — and the third: 38-digit exact decimals
- Http.* — fetching GeoJSON from a service