I have two GPS Coordinates i wanted to calculate distance between those but the result on SQL server is entirely different from result in c# I googled and found that the both approaches return distance in meters but this difference is driving me crazy.
SQL SERVER Query
select geography::Point(25.3132666, 55.2994054 ,4326)
.STDistance(geography::Point(25.25434, 55.32820,4326)) as Distance;
Web API
String format = "POINT(25.25434 55.32820)";
DbGeography myLocation = DbGeography.PointFromText(format, 4326);
var users = context.Users.Select(u => new
{
fullName = u.name,
lat = u.location.Latitude,
lng = u.location.Longitude,
distance = myLocation.Distance(u.location)
}).ToList();
Response
,{"fullName":"jons smith","lat":25.3132666,"lng":55.2994054,"distance":4133581.8647264037}
Thanks in advance.
The geography spatial data type, geography, is implemented as a .NET common language runtime (CLR) data type in SQL Server. This type represents data in a round-earth coordinate system. The SQL Server geography data type stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.
The geography spatial data type, geography, is implemented as a .NET common language runtime (CLR) data type in SQL Server. This type represents data in a round-earth coordinate system.
The geography type is a little bit more restrictive than geometry. It can't cross different hemispheres and the outer ring must be drawn counter-clockwise. The rest can be found in Geography data type vs. Geometry data type in SQL Server.
Spatial Types - geography. The geography spatial data type, geography, is implemented as a .NET common language runtime (CLR) data type in SQL Server. This type represents data in a round-earth coordinate system. The SQL Server geography data type stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.
Check latitude and longitude order in the WKT representation of the point in SQL when defining the point, they are as follow GEOGRAPHY::POINT(Latitude, Longitude, srid)
:
SELECT GEOGRAPHY::Point(25.3132666,55.2994054 ,4326)
.STDistance(GEOGRAPHY::Point(25.25434, 55.32820,4326)) as distance;
//distance: 7142.94965953253
But when defining DBGeography
in C# code, the order is different:"POINT(Longitude Latitude)"
String format = "POINT(55.32820 25.25434)";
DbGeography myLocation = DbGeography.PointFromText(format, 4326);
var users = context.Users.Select(u => new
{
fullName = u.name,
lat = u.location.Latitude,
lng = u.location.Longitude,
distance = myLocation.Distance(u.location)
}).ToList();
//distance: 7142.949659532529
Also you should check those locations inserted in the Users
table. Make sure when inserting they have been correctly inserted. Otherwise they will be somewhere else not the location of your Users
More:
SELECT GEOGRAPHY::Point(25, 55 ,4326).Lat //25
DbGeography.PointFromText("POINT(25 55)", 4326).Latitude.Value //55
Microsoft.SqlServer.Types.SqlGeography.STPointFromText(
new System.Data.SqlTypes.SqlChars("POINT(25 55)"), 4326).Lat.Value;
//55
What is WKT and where does it come from? It's a Well-Known Text representation of different geometry types that is introduce by OGC in the Simple Feature Access specification and all software vendors are advised to follow it in the sake of the compatibility. This specification shows us how to define point, line (linestring), polygon and some other geometry types as text (WKT) and binary (WKB).
SQL Server do not completely follow this specification and we see the result of not following standards, causes such problems in different components of even the same company.
Switch the Lat/Lng in in API Version. In the API, it should go Lng Lat
select geography::Point(25.3132666, 55.2994054 ,4326).STDistance(geography::Point(25.25434, 55.32820,4326)) as Distance
Returns
7142.94965953253
This is where I flipped one Lat/Lng usinq my UDF
Select [dbo].[udf-Geo-Meters](55.2994054,25.3132666 ,25.25434,55.32820)
Returns
4135883.9028193
The issue is very minor but tricky
SQL SERVER Query
geography::Point(25.3132666, 55.2994054 ,4326)
SQL Server defines a point such that first value is latitude and second value is longitude.
Web API
String format = "POINT(25.25434 55.32820)";
DbGeography myLocation = DbGeography.FromText(format);
C# defines a point from above format in such a way that first value is longitude and second value is latitude
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With