【问题标题】:Getting different answers using DbGeography and SqlGeography: Why?使用 DbGeography 和 SqlGeography 获得不同的答案:为什么?
【发布时间】:2017-10-30 18:18:31
【问题描述】:

我正在使用实体框架 v6.1.3 (DbGeography) 和 14.0.314.76 (SqlGeography)。这两个都是最新版本。

DbGeography 代码

        public static double GetDistance(double p1Latitude, double p1Longitude, double p2Latitude, double p2Longitude, int SRID = 4326)
    {
        System.Data.Entity.Spatial.DbGeography p1 = System.Data.Entity.Spatial.DbGeography.FromText(String.Format("POINT({0} {1} {2})", p1Latitude, p1Longitude, SRID));
        System.Data.Entity.Spatial.DbGeography p2 = System.Data.Entity.Spatial.DbGeography.FromText(String.Format("POINT({0} {1} {2})", p2Latitude, p2Longitude, SRID));
        return (double)p1.Distance(p2);
    }

SqlGeography 代码

public static double GetDistance(double p1Latitude, double p1Longitude, double p2Latitude, double p2Longitude, int SRID = 4326)
    {
        SqlGeography p1 = SqlGeography.Point(p1Latitude, p1Longitude, SRID);
        SqlGeography p2 = SqlGeography.Point(p2Latitude, p2Longitude, SRID);
        return (double)p1.STDistance(p2);
    }

DbGeography 给出 179403.75129861536,SqlGeography 给出 217842.34845013986。

我已经检查了 SQL Server 中的计算

declare @p1 geography = geography::Point(-11.98260953020022, 54.51564130011218,4326)
declare @p2 geography = geography::Point(-10.55307433448692, 53.14334572793153,4326)
select @p1.STDistance(@p2)

答案是 217842.34845014。 我还验证了 Google Earth Pro 中创建线串的距离

            <coordinates>
        54.51564130011218,-11.98260953020022,0  53.14334572793153,-10.55307433448692,0 
        </coordinates>

长度为217832。

Dbgeography 调用是:

double x = EF.GetDistance(-11.98260953020022, 54.51564130011218, -10.55307433448692, 53.14334572793153);

SqlGeography 调用是:

            double y = Geography.SQLServerTypes.GetDistance(-11.98260953020022, 54.51564130011218, -10.55307433448692, 53.14334572793153);

我不明白为什么 DbGeography 结果如此遥远。 有什么见解吗? 谢谢。

【问题讨论】:

  • 此类问题的常见问题是人们假设总是先通过纬度,然后通过经度。检查您使用的表单的文档。
  • 有关“有趣”的示例,请查看this question。因为POINT 文本表示同时用于几何和地理,所以它使用x y 坐标,该坐标映射到long lat 而不是lat long。我想你在这里也有同样的问题。
  • 我已经使用 Visual Studio 中的监视窗口验证了坐标的顺序是否正确。我换成使用 PointFromText 而不是 FromText 并且我现在得到了相同的答案。我认为问题在于 FromText 强制进行欧几里得计算,而不是预期的球面计算。即如你所说,FromText 是 Geometry,我需要 Geography。
  • 真的吗?因为如果我将p1.Latitude 放在监视窗口中并跳过DbGeography GetDistance 方法中的分配,我会得到54.5156413001122 的值。所以,正如我一直在说的那样,问题在于您将POINT(Latitude Longitude) 传递给这些文本方法,而它应该POINT(Longitude Latitude)

标签: sql entity-framework spatial geography


【解决方案1】:

当使用众所周知的文本表示时,POINT 的参数是x 坐标,后跟y 坐标。将其映射到地理时,这打破了“预期”约定,因为x 对应于经度,y 对应于纬度。

所以你需要颠倒你传递参数的顺序:

public static double GetDistance(double p1Latitude, double p1Longitude, 
                     double p2Latitude, double p2Longitude, int SRID = 4326)
{
    System.Data.Entity.Spatial.DbGeography p1 = 
     System.Data.Entity.Spatial.DbGeography.FromText(String.Format("POINT({0} {1} {2})",
          p1Longitude, p1Latitude, SRID));
    System.Data.Entity.Spatial.DbGeography p2 =
     System.Data.Entity.Spatial.DbGeography.FromText(String.Format("POINT({0} {1} {2})",
          p2Longitude, p2Latitude, SRID));
    return (double)p1.Distance(p2);
}

这将产生您的预期结果 217842.34845014423。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    相关资源
    最近更新 更多