SQL Server Geography与DbGeography的区别

8
我可以帮助您翻译以下内容:

我有两个GPS坐标,想要计算它们之间的距离,但是在SQL服务器上的结果与C#中的结果完全不同。我搜索了一下并发现这两种方法都返回以米为单位的距离,但是这种差异让我感到很困扰。

SQL SERVER查询

select geography::Point(25.3132666, 55.2994054 ,4326)
                         .STDistance(geography::Point(25.25434, 55.32820,4326)) as Distance;

Result of above sql query

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();

响应

,{"fullName":"jons smith","lat":25.3132666,"lng":55.2994054,"distance":4133581.8647264037}

提前致谢。


如果直接比较你问题中的代码,我们不知道用户的位置在哪里。在 SQL 中,您会硬编码一些坐标。我假设它们与用户坐标不同。 - Andrii Litvinov
要断言两者使用相同的大地测量系统(很可能是WGS 84)。即使如此,我仍然可以想象计算可能会有所不同,例如取决于使用的地球直径(考虑到地球并不是完美的球体)。只是猜测... - CHS
@AndriiLitvinov 我只粘贴了响应中具有完全相同值的记录作为参考,您可以看到该记录的纬度和经度与 SQL 查询的完全相同。 - Muzammal Hussain
3个回答

14

在SQL中定义点的WKT表示中,检查纬度和经度的顺序,它们应该如下所示:GEOGRAPHY::POINT(纬度, 经度, srid)

SELECT GEOGRAPHY::Point(25.3132666,55.2994054 ,4326)
                    .STDistance(GEOGRAPHY::Point(25.25434, 55.32820,4326)) as distance;
//distance: 7142.94965953253

但是在C#代码中定义DBGeography时,顺序是不同的:"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

同时,您应该检查在Users表中插入的这些位置。确保在插入时它们已被正确插入。否则,它们将出现在其他地方而不是您的Users的位置。

更多信息:

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

WKT是什么,它的起源在哪里? 它是由OGC在Simple Feature Access规范中引入的不同几何类型的文本表示方式,被称为“Well-Known Text”。所有软件供应商都建议遵循此规范以确保兼容性。该规范展示了如何将点、线(线串)、多边形和其他一些几何类型定义为文本(WKT)和二进制(WKB)格式。 SQL Server并未完全遵循此规范,我们看到没有遵循标准的结果,在同一公司的不同组件中会导致问题。

4

在API版本中切换经纬度。在API中,应该使用经度和维度的顺序是经度在前,维度在后。

select geography::Point(25.3132666, 55.2994054 ,4326).STDistance(geography::Point(25.25434, 55.32820,4326))  as Distance

返回值

7142.94965953253

这就是我使用我的自定义函数翻转了一个Lat/Lng的位置。

Select [dbo].[udf-Geo-Meters](55.2994054,25.3132666  ,25.25434,55.32820)

返回值

4135883.9028193

2
这个问题很小但是比较棘手。 SQL SERVER查询
geography::Point(25.3132666, 55.2994054 ,4326)

SQL Server 定义了一个点,其第一个值是纬度,第二个值是经度。

Web API

String format = "POINT(25.25434 55.32820)";
DbGeography myLocation = DbGeography.FromText(format);

C#将上述格式定义为一个点,其中第一个值是经度,第二个值是纬度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接