简体   繁体   中英

SQL Server Geography vs DbGeography

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;

以上sql查询的结果

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.

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 W ell- K nown T ext 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM