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...
  },

Мне нужно использовать это для заполнения исходных статических данных, которые будут загружены, но я не знаю, как преобразовать геометрию строки в геометрию NetTopology.

Куда я пошел или и что я пропустил? Есть ли лучший способ для меня засеять эти данные? Или есть способ проанализировать текст, который у меня есть в EF Core, для заполнения геометрии?


person Imran Shaik    schedule 27.08.2020    source источник
comment
Мой длинный ответ (ниже) стал неактуален для WKTReader.   -  person Imran Shaik    schedule 27.08.2020


Ответы (1)


Я нашел ответ, исследуя дальше, и я также закончил тестирование, поэтому подумал, что поделюсь с кем-нибудь в похожей лодке.

Чтобы преобразовать строку в геометрию, используйте GMLReader< /а>

Но для этого мы сгенерируем Gml вместо строки

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

Это создает Xml на SQL Server

  <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 и т. д.), которую ваша база данных использует для декодирования.

ПРЕДУПРЕЖДЕНИЕ. Я столкнулся с проблемой загрузки извлеченного GML с помощью GMLReader после декодирования, потому что возникла проблема с добавлением некоторых недопустимых байтов (SQL Server?). ://stackoverflow.com/questions/17947238/why-data-at-the-root-level-is-invalid-line-1-position-1-for-xml-document/24513288#24513288">XmlException: данные в корневой уровень недействителен. Строка 1, позиция 1.

person Imran Shaik    schedule 27.08.2020