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

2.9k views Asked by At

I have a model named Layer.cs and it has a property named Geometry like:

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

I want to convert a sample GeoJson file (you can find it HERE) to feature collection (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);

and then save it to Layer.Geomerty using:

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

or

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

but after calling save change (in both situations) I got the fallowing error:

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.

Is there any clean solution to save a GeoJson file as NetTopologySuite.Geometries.Geometry using EF Core 5?

1

There are 1 answers

2
Seyed Arman Fatemi On BEST ANSWER

After a bunch of trials and errors, I founded a comprehensive solution to this.

Database and models

when we dealing with a GeoJson file, each feature can (or even should!) save in a separate NetTopologySuite.Geometries.Geometry type. (in other words, I changed the structure of my table from one stand-alone table to two tables with a parent child relationship)

Serialization

In fact, we don't need to serialize any things manually when are using NetTopologySuite.IO.GeoJSON4STJ. in our code, we only need to work with NetTopologySuite.Features.FeatureCollection and add NetTopologySuite.IO.Converters.GeoJsonConverterFactory to JSON converters when we add controllers. but there is also a trick here, at the registration time we should use NetTopologySuite.Geometries.GeometryFactoryEx instead of NetTopologySuite.Geometries.GeometryFactory (attention to the Ex word at the end). the reason for this is SQL server Require left-hand-rule (CCW) but GeoJson Required right-hand-rule (REFRENCE) so:

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

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