I have a project that need to take geometry data from DataBase and based on that data create KML file.
For small amout of data it create KML file, but when I try it to create for example 600.000 geo locations data and create KML file I get out of memory error.
To create KML file I use SharpKml library. Usualy I get this error when I try this code
var kml = new Kml { Feature = document };
KmlFile kmlFile = KmlFile.Create(kml, true);
var stream = new MemoryStream();
kmlFile.Save(stream); <=== I think here
files.Add(new KeyValuePair<string, Stream>(fileName, stream));
return files;
Please help me or give me advice how can I solve this problem, are there any way to do this. I think I can use Azure blob storage to store this file by chunks. But how can I get this by chunks or how to save it by chunks.
Maybe the error is not related to Memory, maybe is about create KML, if there are any way to solve help me.
If you had a any experience with this problem please give me advice,
Thanks
I use this function to create KML file, If you have any suggestion please let me know.
public List<KeyValuePair<string, Stream>> ExportToKml(List<dynamic> exportedData, string exportBy, string geometry)
{
var documentAll = new Document();
List<KeyValuePair<string, Stream>> files = new();
string fileNameAll = $"All_{exportBy}.kml";
var providers = exportedData.Select(p => new { p.ProviderId, p.ProviderName }).Distinct().ToList();
var technologies = exportedData.Select(t => new { t.TechCode, t.TechnologyName }).Distinct().ToList();
foreach (var provider in providers)
{
foreach (var technology in technologies)
{
dynamic providerTechCnties = exportedData.Where(c => c.ProviderId == provider.ProviderId
&& c.TechCode == technology.TechCode).Distinct().ToList();
string fileName = $"{provider.ProviderName}_{technology.TechnologyName}_{exportBy}.kml";
if (providerTechCnties.Count != 0)
{
var document = new Document();
int entrance = 0;
Random _random = new();
byte byte_Color_R = Convert.ToByte(_random.Next(250)),
byte_Color_G = Convert.ToByte(_random.Next(250)),
byte_Color_B = Convert.ToByte(_random.Next(250)),
byte_Color_A = 225;
foreach (var kmlData in providerTechCnties)
{
CoordinateCollection coordinates = new CoordinateCollection();
Placemark placemark = new();
Placemark placemarkAll = new();
OuterBoundary outerBoundary = new();
Polygon polygon = new();
Point point = new();
LineString line = new();
var style = new Style();
var styleAll = new Style();
if (geometry == "polygon")
{
List<string> geomCoords = new();
if (kmlData.Coordinate is not null)
{
string[] coordSplit = kmlData.Coordinate.Replace(' ', ',').Replace("),", ")")
.Split(new string[] { "(", ")" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < coordSplit.Count(); i++)
{
geomCoords.Add(coordSplit[i]);
}
}
string[] coord = Array.Empty<string>();
if (geomCoords?.Count != 0) { coord = geomCoords[1]?.ToString().Split(','); }
for (int i = 0; i < coord.Length; i += 2)
{
double lat = double.Parse(coord[i].ToString());
double lon = double.Parse(coord[i + 1].ToString());
coordinates.Add(new Vector(lon, lat));
}
outerBoundary.LinearRing = new LinearRing { Coordinates = coordinates };
polygon.Extrude = true;
polygon.AltitudeMode = AltitudeMode.ClampToGround;
polygon.OuterBoundary = outerBoundary;
}
else if (geometry == "point")
{
point.Coordinate = new Vector(Convert.ToDouble(kmlData.Lat), Convert.ToDouble(kmlData.Lon));
}
else if (geometry == "line")
{
List<string> geomCoords = new();
if (kmlData.Coordinate is not null)
{
string[] coordSplit = kmlData.Coordinate.Replace(' ', ',').Replace("),", ")")
.Split(new string[] { "(", ")" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < coordSplit.Count(); i++)
{
geomCoords.Add(coordSplit[i]);
}
}
string[] coord = Array.Empty<string>();
if (geomCoords?.Count != 0) { coord = geomCoords[1]?.ToString().Split(','); }
line.Coordinates = new CoordinateCollection();
for (int i = 0; i < coord.Length; i += 2)
{
double lat = double.Parse(coord[i].ToString());
double lon = double.Parse(coord[i + 1].ToString());
line.Coordinates.Add(new Vector(lon, lat));
}
}
PropertyInfo[] pkmlDataProps = kmlData.GetType().GetProperties();
if (entrance == 0)
{
Dictionary<string, string> cntySimpleFields = new Dictionary<string, string>();
foreach (PropertyInfo pkmlDataProp in pkmlDataProps)
{
if (pkmlDataProp.Name != "Coordinate") cntySimpleFields.Add(pkmlDataProp.Name, "string");
}
Schema cntySchema = new Schema();
Schema cntySchemaAll = new Schema();
foreach (var cntySimpleField in cntySimpleFields)
{
SimpleField simpleField = new SimpleField
{
Name = cntySimpleField.Key,
FieldType = cntySimpleField.Value
};
SimpleField simpleFieldAll = new SimpleField
{
Name = cntySimpleField.Key,
FieldType = cntySimpleField.Value
};
cntySchema.AddField(simpleField);
cntySchemaAll.AddField(simpleFieldAll);
}
document.AddSchema(cntySchema);
documentAll.AddSchema(cntySchemaAll);
entrance++;
}
placemark.ExtendedData = new ExtendedData();
placemarkAll.ExtendedData = new ExtendedData();
Dictionary<string, dynamic> cntySimpleDatas = new Dictionary<string, dynamic>();
foreach (PropertyInfo pkmlDataProp in pkmlDataProps)
{
if (pkmlDataProp.Name != "Coordinate") cntySimpleDatas.Add(pkmlDataProp.Name, pkmlDataProp.GetValue(kmlData, null)?.ToString());
}
SchemaData cntySchemaData = new SchemaData();
SchemaData cntySchemaDataAll = new SchemaData();
foreach (var cntySimpleData in cntySimpleDatas)
{
SimpleData simpleData = new SimpleData
{
Name = cntySimpleData.Key,
Text = cntySimpleData.Value
};
SimpleData simpleDataAll = new SimpleData
{
Name = cntySimpleData.Key,
Text = cntySimpleData.Value
};
cntySchemaData.AddData(simpleData);
cntySchemaDataAll.AddData(simpleDataAll);
}
placemark.ExtendedData.AddSchemaData(cntySchemaData);
placemarkAll.ExtendedData.AddSchemaData(cntySchemaDataAll);
style.Polygon = new PolygonStyle();
style.Polygon.ColorMode = ColorMode.Normal;
style.Polygon.Color = new Color32(byte_Color_A, byte_Color_B, byte_Color_G, byte_Color_R);
style.Balloon = new BalloonStyle();
style.Balloon.BackgroundColor = new Color32(byte_Color_A, byte_Color_B, byte_Color_G, byte_Color_R);
styleAll.Polygon = new PolygonStyle();
styleAll.Polygon.ColorMode = ColorMode.Normal;
styleAll.Polygon.Color = new Color32(byte_Color_A, byte_Color_B, byte_Color_G, byte_Color_R);
styleAll.Balloon = new BalloonStyle();
styleAll.Balloon.BackgroundColor = new Color32(byte_Color_A, byte_Color_B, byte_Color_G, byte_Color_R);
if (geometry == "polygon")
{
placemark.Geometry = polygon;
placemarkAll.Geometry = polygon;
}
else if (geometry == "point")
{
placemark.Geometry = point;
placemarkAll.Geometry = point;
}
else if (geometry == "line")
{
placemark.Geometry = line;
placemarkAll.Geometry = line;
}
placemark.AddStyle(style);
placemarkAll.AddStyle(styleAll);
document.AddFeature(placemark);
documentAll.AddFeature(placemarkAll);
}
document.Id = exportBy;
document.Name = fileName;
var kml = new Kml { Feature = document };
KmlFile kmlFile = KmlFile.Create(kml, true);
var stream = new MemoryStream();
kmlFile.Save(stream);
files.Add(new KeyValuePair<string, Stream>(fileName, stream));
}
}
}
documentAll.Id = exportBy;
documentAll.Name = fileNameAll;
var kmlAll = new Kml { Feature = documentAll };
KmlFile kmlFileAll = KmlFile.Create(kmlAll, true);
var streamAll = new MemoryStream();
kmlFileAll.Save(streamAll);
files.Add(new KeyValuePair<string, Stream>(fileNameAll, streamAll));
return files;
}