EF Core:如何通过解析空间数据创建几何

问题描述

我需要存储带有某些多边形的静态空间数据,我将GeoJson导入到sql Server中以处理辅助数据,一旦获得正确的数据,就将数据导出到Json中(使用FOR JSON PATH)。

现在,由于几何是CLR类型,因此我需要将其转换为字符串以允许导出为JSON。

SELECT 
    Id,Bounds.ToString() as Bounds 
FROM
    ...
FOR JSON PATH

在这产生了一个JSON文件

  [{
    "Id": 1,"Bounds": "polyGON ((93.044663537224707 23.410524583651519,...
  },{
    "Id": 2,"Bounds": "MULTIpolyGON (((93.046192725017278 23.666228900665988...
  },

我需要使用它来播种初始静态数据,该静态数据将从中加载,但我不知道如何将字符串Geometry转换为NetTopology Geometry。

我去哪里了,或者我想念什么?我有更好的方式播种此数据吗?还是有一种方法可以解析我在EF Core中拥有的文本以填充几何图形?

解决方法

我通过进一步的研究找到了答案,并且我也完成了测试,因此我想与其他类似的人分享。

将字符串解析为Geometry的方法是使用GMLReader

但是为此,我们生成了Gml而不是字符串

SELECT 
Id,Bounds.AsGml() as Bounds 
FROM
    ...

这会在SQL Server上生成Xml

  <Bounds>
    <Polygon xmlns="http://www.opengis.net/gml">
      <exterior>
        <LinearRing>
          <posList>93.044663537224707 23.410524583651519 92.9467955185...

但这只能解决我一半的问题,我需要生成JSON并在播种中使用该JSON,但是如果我灵活地使用XML,则可以使用XML种子数据导出

SELECT 
  [Id],[Bounds].AsGml() as Bounds
  ...
FROM ...
FOR XML PATH

会用如下数据生成XML。

<row>
  <Id>1</Id>
  <Bounds>
    <Polygon xmlns="http://www.opengis.net/gml">
      <exterior>
        <LinearRing>
          <posList>93.044663537224707 23.410524583651519 92.9467955185...

因此,我决定将生成的GML编码为Base64以生成JSON,在解析几何体以进行播种时,将对该Base64进行解码。

    CREATE FUNCTION [dbo].[Geometry_Encode_Gml_Base64]
    (
        @value geometry
    )
    RETURNS varchar(max)
    AS
    BEGIN
        DECLARE @source varbinary(max) = convert(varbinary(max),@value.AsGml())
        RETURN cast(N'' as xml).value('xs:base64Binary(sql:variable("@source"))','varchar(max)')
    END

并通过执行查询生成JSON

SELECT 
  [Id],dbo.Geometry_Encode_Gml_Base64([Bounds]) as Bounds
  ...
FROM ...
FOR JSON PATH

会产生类似JSON的

[
  {
    "Id": 1,"Bounds": "\/\/48AFAAbwBsAHkAZwBvAG4AIAB4AG0AbABuAHMAPQAiAGgAdAB0AH..."
},...

现在,在读取和播种时,我可以简单地解码Base64字符串并使用GMLReader读取它

GMLReader gmlReader = new GMLReader(NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326));

Geometry bounds = gmlReader.Read(DecodeBase64(jsonRow.Bounds))

注意:DecodeBase64应该使用数据库用来解码的编码(Unicode / Utf8等)

警告:解码后,我在用GMLReader加载提取的GML时遇到问题,因为添加了一些非法字节(SQL Server?)时出现问题,如果您发现相同的问题,请查看如何解决{{3 }}