【问题标题】:SQL Server Geography vs DbGeographySQL Server 地理与 DbGeography
【发布时间】:2017-05-18 12:52:13
【问题描述】:

我有两个 GPS 坐标,我想计算它们之间的距离,但 SQL 服务器上的结果与 c# 中的结果完全不同p>

SQL SERVER 查询

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

响应

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

提前致谢。

【问题讨论】:

  • 如果直接比较您问题中的代码,我们不知道用户的位置。在 SQL 中,您对一些坐标进行硬编码。我假设它们与用户坐标不同。
  • 断言两者都使用相同的大地测量系统(很可能是 WGS 84)。尽管如此,我还是可以想象微积分可能会有所不同,例如取决于使用的地球直径(考虑到地球不是一个完美的球体)。只是猜测......
  • @AndriiLitvinov 我只粘贴了响应中的记录作为具有完全相同值的参考,您可以看到记录的纬度长度与 SQL-Query 的完全相同

标签: c# .net sql-server entity-framework geospatial


【解决方案1】:

在定义点时检查点在SQL中WKT表示中的经纬度顺序,如下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

但是在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-K已知Text 表示为了兼容性,建议遵循它。该规范向我们展示了如何将点、线(线串)、多边形和其他一些几何类型定义为文本(WKT)和二进制(WKB)。

SQL Server 没有完全遵循这个规范,我们看到不遵循标准的结果,甚至在同一家公司的不同组件中也会出现这样的问题。

【讨论】:

    【解决方案2】:

    在 API 版本中切换 Lat/Lng。在 API 中,它应该是 Lng Lat

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

    退货

    7142.94965953253
    

    这是我使用我的 UDF 翻转一个纬度/经度的地方

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

    退货

    4135883.9028193
    

    【讨论】:

      【解决方案3】:

      这个问题很小但很棘手

      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#从上述格式定义一个点,第一个值是经度,第二个值是纬度

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-15
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多