使用 ef core 5 将 GeoJson 转换为 FeatureCollection 并保存在 NetTopologySuite.Geometries.Geometry 列中

Convert GeoJson to FeatureCollection and save in NetTopologySuite.Geometries.Geometry column using ef core 5

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

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

我想将示例 GeoJson 文件(您可以找到它 HERE)转换为特征集合(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));

但在调用保存更改后(在两种情况下)我得到了休闲错误:

The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 3 ("@p2"): The supplied value is not a valid instance of data type geography. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision.

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

经过反复试验,我找到了一个全面的解决方案。

数据库和模型

当我们处理 GeoJson 文件时,每个特征都可以(甚至应该!)保存在 单独的 NetTopologySuite.Geometries.Geometry 类型。 (换句话说,我 将我的 table 的结构从一个独立的 table 更改为两个 table有亲子关系)

序列化

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

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

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