从纬度和经度双精度构建 DbGeography 点?

43

我想用纬度和经度双精度浮点数构建一个 DbGeography 点。

我知道我可以将我的双精度浮点数转换为字符串并使用 DbGeography.FromText 方法。

var latitude = 50.0d;
var longitude = 30.0d;

var pointString = string.Format(
    "POINT({0} {1})",
    longitude.ToString(),
    latitude.ToString());

var point = DbGeography.FromText(pointString);

然而,将我的双精度浮点数转换为字符串,再让 DbGeography 将它们解析为双精度浮点数似乎是一种浪费。


我尝试直接构造 DbGeography,像这样:

var point = new DbGeography()
{
    Latitude = 50,
    Longitude = 30
};

但是纬度和经度属性是只读的。(这很有道理,因为DbGeography类处理的不仅仅是单个点)


DbGeography类还提供了一个接受字节数组的FromBinary方法。我不知道如何将我的纬度和经度double转换为正确格式的字节数组。

有没有比顶部代码更简单的方法来构建一个由纬度和经度double组成的DbGeography实例?


1
为什么不创建一个方法 public static DbGeography CreatePoint(double, double) 来包装你的代码呢?这样做虽然不能避免转换,但至少可以让你的代码更清晰。 - Raphaël Althaus
我可能最终会做类似的事情。很遗憾没有静态扩展方法;我希望能够将所有静态的DbGeography创建方法都放在一个类下面。 - jcarpenter2
2
虽然这并不太有帮助,但是在 C# 的 6 版本及以上中,你可以使用字符串插值来实现:DbGeography.FromText($"POINT({longitude} {latitude})"); - Martin Brown
4个回答

55

简而言之,答案是否定的。

SqlGeography有一个相应的方法:

Microsoft.SqlServer.Types.SqlGeography.Point(latitude, longitude, srid);

...但是您仍然需要将其转换为DbGeography。如果您对此感兴趣,请参见我以前有关转换的答案:DbGeography to SqlGeography(以及相反)

话虽如此,我完全同意Raphael Althaus的看法,即您应该创建一个静态方法来使生活更轻松:

public static DbGeography CreatePoint(double lat, double lon, int srid = 4326)
{
    string wkt = String.Format("POINT({0} {1})", lon, lat);

    return DbGeography.PointFromText(wkt, srid);
}

然后所有的使用都可以通过该方法进行。

编辑

@Korayem提出了一个很好的建议,事实上自问答问题以来我也已经这样做了。大多数人使用SRID 4326,因此我们可以将其作为参数默认值,使静态方法更易于使用。


3
这里可以找到一个有用的GeoUtils类,其中包含CreatePoint方法:http://codepaste.net/73hssg。 - Zharro
@Zharro 尽管很容易根据用户需求进行修改,但上述示例还允许动态 SRID 值,而 GeoUtils 则假定为 4326。有些人需要不同的 SRID(并可以简单地更改数字),但有些人使用多个 SRID,并且在方法参数中指定它的能力可以实现这一点。 - Jon Bellamy
你好。在我的场景中,我想存储简单的纬度和经度值。我应该使用 DbGeography 存储还是创建一个简单的复杂类型?使用 DbGeography 有什么优势? - Shimmy Weitzhandler
1
@Shimmy 如果您想使用空间函数(例如最近位置等),则可以从中获益。如果您没有进行任何此类操作,则没有实际好处。您可以创建一个复杂类型,但如果您这样做,那么最好使用DbGeography(SqlGeography),并只需创建两个列。 - Jon Bellamy
1
我还建议将答案始终更改为使用CultureInfo.InvariantCulture。 在我的文化中,逗号是十进制分隔符,因此这段代码一开始并没有正常工作。 - FiDO
显示剩余3条评论

0
你可以这样简化它:
  DbGeography.FromText(String.Format(CultureInfo.InvariantCulture, "POINT({0} {1})", longitude, latitude));

例如:

DbGeography.FromText("POINT(-73.935242 40.730610)"),

不要使用默认值 int srid = 4326;

如果您需要多次使用它,请在静态方法中使用:

private static DbGeography CreatePoint(double latitude, double longitude)
{
    return DbGeography.FromText(String.Format(CultureInfo.InvariantCulture, "POINT({0} {1})", longitude, latitude));
}

PS:不要忘记使用 CultureInfo.InvariantCulture,因为有些语言环境会抛出异常。


0

你可以使用SqlGeographyBuilder来完成它。

                SqlGeographyBuilder sqlGeographyBuilder = new SqlGeographyBuilder();
                sqlGeographyBuilder.SetSrid(4326);
                sqlGeographyBuilder.BeginGeography(OpenGisGeographyType.Polygon);
                sqlGeographyBuilder.BeginFigure(37.944197500754 ,- 127.24365234375);
                sqlGeographyBuilder.AddLine(37.944197500754 ,- 80.68359375);
                sqlGeographyBuilder.AddLine(24.966140159913 ,- 80.68359375);
                sqlGeographyBuilder.AddLine(24.966140159913 ,- 127.24365234375);
                sqlGeographyBuilder.AddLine(37.944197500754 ,- 127.24365234375);
                sqlGeographyBuilder.EndFigure();
                sqlGeographyBuilder.EndGeography();

                SqlGeography polygon = sqlGeographyBuilder.ConstructedGeography;

0
假设您的目标是SQL Server,您可以在不进行字符串解析的情况下完成它。首先创建一个SqlGeography对象:
var sqlPoint = Microsoft.SqlServer.Types.SqlGeography.Point(latitude, longitude, srid);

然后从这个SqlGeography创建一个DbGeography(请参见我关于DbGeography转换的答案的单独问题)。

var dbPoint = System.Data.Entity.SqlServer.SqlSpatialServices.Default.GeographyFromProviderValue(sqlPoint);

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