I am using Openlayers and trying to save the geometry information in my DB.
When i draw a polygon on openlayers map, the object(feature) generated is in this format
{
"type": "Polygon",
"coordinates": [
[
[
54.86572265625,
74.0013854318592
],
[
53.59130859375,
73.62159408606237
],
[
53.96484375,
73.16953636227885
],
[
55.986328125,
73.59679245247814
]
]
]
}
Above object has 2 properties. {type: string, coordinates: someNestedArray}
I am passing this object to my API to save it in DB. But am facing issue with defining type of coordinates property.
Basically it is of type float[][][] so i created my EF model class as below
public class Geometry
{
public string Type { get; set; }
public float[][][] Coordinates { get; set; }
}
when i try to get/update, EF is throwing below error
{"The property 'Geometry.Coordinates' could not be mapped, because it is of type 'float[][][]'
which is not a supported primitive type or a valid entity type. Either explicitly map this property,
or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'."}
the error is clear. EF cannot map these un-supported types on its own. How can i define a mapping explicitly ? Or is there any way i can make it work ? is the type float[][][] correct ?
Thanks in advance.
CodePudding user response:
You can always save coordinates as string where coordinates are separated by comma.
For instance in FE part you can handle it like this:
const someLine = feature.getGeometry().transform("EPSG:4326",
"EPSG:3857");
const geometryLine = someLine
.clone()
.getGeometry()
.transform("EPSG:3857", "EPSG:4326");
const geometryCoords = geometryLine.getCoordinates().join(";");
Then you will get something like this: "43.520548594674132,26.565803087473146;...." which can be saved to database as a string. (it can be additionally tweaked with fewer decimal points, etc..)
After that, if you want to handle/fetch data through API and map it via automapper(or some custom implementation)to List of Coordinates (for example something like this)
public class Coordinates
{
public double Longitude { get; set; }
public double Latitude { get; set; }
}
To map previously saved data to DTO you can use something like this
public class GeneralProfile : Profile
{
public GeneralProfile()
{
CreateMap<Route, GetSavedRouteDTO>()
.ForMember(x => x.TripLength, options => options.MapFrom(x => x.Length))
.ForMember(x => x.RouteCoordinates, options => options.MapFrom(MapFromStringCoordinates));
CreateMap<Route, RouteCreateDTO>().ReverseMap();
}
private List<Coordinates> MapFromStringCoordinates(Route route, GetSavedRouteDTO getSavedRouteDTO)
{
var currentCulture = System.Globalization.CultureInfo.InstalledUICulture;
var numberFormat = (System.Globalization.NumberFormatInfo)currentCulture.NumberFormat.Clone();
numberFormat.NumberDecimalSeparator = ".";
var coordinates = new List<Coordinates>();
var coordinatesSplit = route.Coordinates.Split(";");
foreach (var coord in coordinatesSplit)
{
var currentCoord = coord.Split(",");
if (currentCoord.Length > 1)
{
var latitude = double.Parse(currentCoord[0], numberFormat);
var longitude = double.Parse(currentCoord[1], numberFormat);
var coords= new Coordinates { Latitude = latitude, Longitude = longitude };
coordinates.Add(coords);
}
}
return coordinates;
}
}
With that you ll get the list of coordinates that will contain latitude and longitude and from which will you create geometry entity.