I have a simple project, using MVC pattern, ET and WCF. It uses Dijkstra to find paths between cities. This is the class itself.
However, when calling FindPathFromCityToCity()
with two same lists in the map
object, same from
and to
, when it's on a normal console application it returns the desired result. However, when used from WCF, it fails on line 39 with exception System.Collections.Generic.KeyNotFoundException
.
In order to check whether if my input is incorrect I added that writing to a txt file (line 17 to 27) and this is what it results (TL;DR - both are exactly the same):
Console:
COUNT: 14 - RANGE 120
FROM: Aalborg - TO: Copenhagen
C: Frederikshavn - E: 2 - T: BLL.BatteryCenter
C: Aalborg - E: 6 - T: BLL.BatteryCenter
C: Hobro - E: 4 - T: BLL.BatteryCenter
C: Randers - E: 6 - T: BLL.BatteryCenter
C: Viborg - E: 8 - T: BLL.BatteryCenter
C: Aarhus - E: 8 - T: BLL.BatteryCenter
C: Herning - E: 6 - T: BLL.BatteryCenter
C: Vejle - E: 8 - T: BLL.BatteryCenter
C: Kolding - E: 6 - T: BLL.BatteryCenter
C: Odense - E: 6 - T: BLL.BatteryCenter
C: Aabenraa - E: 2 - T: BLL.BatteryCenter
C: Koge - E: 4 - T: BLL.BatteryCenter
C: Copenhagen - E: 2 - T: BLL.BatteryCenter
C: Soro - E: 4 - T: BLL.BatteryCenter
WCF:
COUNT: 14 - RANGE 120
FROM: Aalborg - TO: Copenhagen
C: Frederikshavn - E: 2 - T: BLL.BatteryCenter
C: Aalborg - E: 6 - T: BLL.BatteryCenter
C: Hobro - E: 4 - T: BLL.BatteryCenter
C: Randers - E: 6 - T: BLL.BatteryCenter
C: Viborg - E: 8 - T: BLL.BatteryCenter
C: Aarhus - E: 8 - T: BLL.BatteryCenter
C: Herning - E: 6 - T: BLL.BatteryCenter
C: Vejle - E: 8 - T: BLL.BatteryCenter
C: Kolding - E: 6 - T: BLL.BatteryCenter
C: Odense - E: 6 - T: BLL.BatteryCenter
C: Aabenraa - E: 2 - T: BLL.BatteryCenter
C: Koge - E: 4 - T: BLL.BatteryCenter
C: Copenhagen - E: 2 - T: BLL.BatteryCenter
C: Soro - E: 4 - T: BLL.BatteryCenter
Can someone see any reason for that to happen?
EDIT:
I did further tests, printing everything possible of the objects with this snippet and there is no difference in the objects (except hash of course):
using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\log\check.txt", true))
{
foreach (var m in map.Stations)
{
file.WriteLine(" --- {0} - {1} - {2} - {3} --- ", m.name, m.Edgelist.Count, m.GetType(), m.GetHashCode());
foreach(var e in m.Edgelist)
{
file.WriteLine();
file.WriteLine(" # {0} - {1} - {2} - {3}", e.BatteryStation.name, e.BatteryStation1.name, e.distance, e.edgeID);
file.WriteLine(" + {0} - {1} - {2}", e.BatteryStation.GetType(), e.BatteryStation.stationID, e.BatteryStation.GetHashCode());
file.WriteLine(" - {0} - {1} - {2}", e.BatteryStation1.GetType(), e.BatteryStation1.stationID, e.BatteryStation1.GetHashCode());
}
file.WriteLine();
}
}
This all hinges on the mechanics of the BatteryCenter
object.
The calling code is passing it in as a parameter, and the function is using it as a key in the map.
Have you overridden the functions Equals
and GetHashCode
on BatteryCenter
?
If not, then the dictionary lookup will be searching for that exact object. Not a BatteryCenter
with all of the same fields, but the object with the same reference.
The WCF client would be passing in an equivalent but nonetheless different BatteryCenter
, which the dictionary is failing to find.
Once you add overrides for BatteryCenter.Equals
and BatteryCenter.GetHashCode
this would probably work.
eg
public override int GetHashCode()
{
return this.stationID.GetHashCode() ^ this.name.GetHashCode();
}
public override bool Equals(Object obj)
{
if(Object.ReferenceEquals(this, obj))
{
return true;
}
BatteryStation other = obj as BatteryStation;
if(Object.ReferenceEquals(other, null))
{
return false;
}
return ((this.stationID == other.stationID) && (this.name == other.name));
}