首页 > 解决方案 > 使用 ef core 5 将 GeoJson 转换为 FeatureCollection 并保存在 NetTopologySuite.Geometries.Geometry 列中

问题描述

我有一个名为Layer.cs的模型,它有一个名为Geometry的属性,例如:

public NetTopologySuite.Geometries.Geometry Geometry { get; set; }

我想将示例 GeoJson 文件(您可以在此处找到)转换为特征集合(NetTopologySuite.Features.FeatureCollection):

// create NetTopology JSON reader
var reader = new NetTopologySuite.IO.GeoJsonReader();

// pass geoJson's FeatureCollection to read all the features
var featureCollection = reader.Read<NetTopologySuite.Features.FeatureCollection>(josnData);

然后将其保存到 Layer.Geomerty 使用:

layer.Geometry = 
 NetTopologySuite.Geometries.Geometry.DefaultFactory.CreateGeometryCollection(featureCollection.Select(c => c.Geometry).ToArray());

或者

layer.Geometry = 
 NetTopologySuite.Geometries.Geometry.DefaultFactory.BuildGeometry(featureCollection.Select(c => c.Geometry));

但是在调用 save change 之后(在这两种情况下)我得到了休闲错误:

传入的表格数据流 (TDS) 远程过程调用 (RPC) 协议流不正确。参数 3 ("@p2"):提供的值不是数据类型 geography 的有效实例。检查源数据中的无效值。无效值的一个示例是小数位数大于精度的数值类型数据。

是否有任何干净的解决方案可以使用 EF Core 5 将 GeoJson 文件保存为 NetTopologySuite.Geometries.Geometry?

标签: c#.net-coregeojsonnettopologysuite

解决方案


经过大量的试验和错误,我为此建立了一个全面的解决方案。

数据库和模型

当我们处理 GeoJson 文件时,每个特征都可以(甚至应该!)保存在单独的 NetTopologySuite.Geometry.Geometry 类型中。(也就是说,我把我的表结构从一张单机表改成了两张有父子关系的表)

序列化

事实上,在使用NetTopologySuite.IO.GeoJSON4STJ时,我们不需要手动序列化任何东西。在我们的代码中,我们只需要使用NetTopologySuite.Features.FeatureCollection并在添加控制器时将NetTopologySuite.IO.Converters.GeoJsonConverterFactory添加到 JSON 转换器。但是这里也有一个技巧,在注册的时候我们应该使用NetTopologySuite.Geometries.GeometryFactoryEx而不是NetTopologySuite.Geometries.GeometryFactory(注意最后的 Ex 字)。原因是 SQL server 需要左手规则 (CCW) 但 GeoJson 需要右手规则 ( REFRENCE ) 所以:

.AddJsonOptions(configure =>
{
  var geometryFactoryEx = new GeometryFactoryEx(new PrecisionModel(), 4326)
  {
    OrientationOfExteriorRing = LinearRingOrientation.CounterClockwise,
  };

  configure.JsonSerializerOptions.Converters.Add(new GeoJsonConverterFactory(geometryFactoryEx));
})

推荐阅读