I'm loading three kinds of entities from an API (in csv format unfortunately). While the first two are fine, the third has foreign keys to both of them. What I'm currently doing is constructing the first two lists and then while constructing the third list I assign the entities for every item. This is how it looks:
var platforms = await Task.Run(() => parsed.Data.Select(p => CreatePlatform(p,stations,lines)).ToList());
private static Platform CreatePlatform(Dictionary<string, string> data, List<Station> stations, List<Line> lines)
{
if (data.Keys.Except(PlatformFields).Any())
return null; // TODO log; invalid data format
Platform platform = null;
try
{
platform = new Platform
{
SteigId = Convert.ToInt32(data["STEIG_ID"]),
Richtung = data["RICHTUNG"],
Reihenfolge = Convert.ToInt32(data["REIHENFOLGE"]),
RblNummer = string.IsNullOrEmpty(data["RBL_NUMMER"]) ? null : (int?) Convert.ToInt32(data["RBL_NUMMER"]),
Bereich = string.IsNullOrEmpty(data["BEREICH"])? null : (int?) Convert.ToInt32(data["BEREICH"]),
Steig = data["STEIG"],
SteigWgs84Lat = Convert.ToDouble(data["STEIG_WGS84_LAT"]),
SteigWgs84Lon = Convert.ToDouble(data["STEIG_WGS84_LON"]),
Stand = data["STAND"],
Station = stations.Single(s => s.HaltestellenId == Convert.ToInt32(data["FK_HALTESTELLEN_ID"])),
Line = lines.Single(l => l.LinienId == Convert.ToInt32(data["FK_LINIEN_ID"]))
};
}
catch (FormatException ex)
{
return null; // TODO log;
}
return platform;
}
Stations and Lines are sets that have been constructed in the exact same way (only without fk's). Hirarchy-wise I want the Stations to include a list of plattforms and each platform has the corresponding line. I also get this using the current method as entity framework handles the dependencies.
My problem is that this method of runnig two selects for every Platform item takes multiple seconds and i'm using this data for input suggestions which i'd like to be available as soon as possible
Is there a more efficient way of assigning the correct dependencies?
If there's some important information missing please tell me
1 Answer 1
Using .Single()
on an unsorted list has O(n) cost. If you use a data structure with constant time lookups e.g. a Dictionary<int, Station>
and a Dictionary<int, Line>
instead you should see a performance improvement using key lookup:
Station = stations[Convert.ToInt32(data["FK_HALTESTELLEN_ID"])],
Line = lines[Convert.ToInt32(data["FK_LINIEN_ID"])]
As you're using Single, I assumed that the dictionary will definitely contain the entry.
I don't know how you're creating your Lists but there is the Enumerable.ToDictionary
method which could be useful:
var stationsLookup = stations.ToDictionary(s => s.HaltestellenId);
stations
andlines
contain no more then one appropriate item thenFirst
instead ofSingle
will give you better performance \$\endgroup\$