I'm writing a WCF application that generates sets of data, and allows the client to create them, navigate through them, and retrieve data from them. The data is stored in static variables of the service class. Particuarly, they're stored in a dictionary, using GUID strings as the keys.
I'm setting the instancing mode of the service class to PerSession, which as far as I know should work. The client calls a function called CreateRecordSet, which adds an entry to the dictionary and returns the key string. The client then calls a function called First(), which should retrieve the first record in the data set. However, when it attempts this, the dictionary no longer contains any entries.
Strangely enough, if I set the instancing mode to Single, it works fine. But, if I set it to PerSession, it seems to lose the dictionary between the two calls, which I would expect if I had set it to PerCall.
Here's the interface definition:
namespace OrsonServiceLibrary
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string CreateRecordSet();
[OperationContract]
object First(string setkey);
// Removed unused methods
}
[DataContract]
[KnownType(typeof(JMMCustomer))]
public class JMMCustomer
{
[DataMember]
public string CUSTFNAME { get; set; }
[DataMember]
public string CUSTLNAME { get; set; }
[DataMember]
public string CUSTADDRESS { get; set; }
[DataMember]
public string CUSTCITY { get; set; }
[DataMember]
public string CUSTKEY { get; set; }
}
}
Here's the service class code:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class Service1 : IService1
{
protected static Dictionary<String,RecordSet> RecordSets;
public Service1()
{
RecordSets = new Dictionary<string,RecordSet>();
}
public string CreateRecordSet()
{
List<object> c = new List<object>(GetAllCustomers());
var rs = new RecordSet(c);
string thekey = System.Guid.NewGuid().ToString();
RecordSets.Add(thekey, rs);
Console.WriteLine("End of CreateRecordSet(). RecordSets.Count = " + RecordSets.Count);
return thekey;
}
public object First(string setkey)
{
Console.WriteLine("Beginning of First(). RecordSets.Count = " + RecordSets.Count);
if (RecordSets[setkey].thelist.Count < 1)
throw new Exception ("No items in the data set.");
else
RecordSets[setkey].cursor = 0;
return RecordSets[setkey].thelist[RecordSets[setkey].cursor];
}
// Removed unused methods
}
Here's the client code:
static void Main(string[] args)
{
Console.WriteLine("Press Enter to begin.");
Console.ReadLine();
ServiceReference1.Service1Client MyService = new ServiceReference1.Service1Client("Service1");
string sk = MyService.CreateRecordSet();
ServiceReference1.JMMCustomer jc;
jc = (ServiceReference1.JMMCustomer)MyService.First(sk);
Console.WriteLine(jc.CUSTFNAME + " " + jc.CUSTLNAME);
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
As you can see, I add some debugging messages to the hosts's console to show the status of the dictionary. Here's the hosts's output:
Host started. Press Enter to terminate host.
End of CreateRecordSet(). RecordSets.Count = 1
Beginning of First(). RecordSets.Count = 0
And then of course, I get an exception in the next line of code in First() when I try to reference RecordSets[setkey] because RecordSets is empty.
If I change the behavior to:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
...it then works as expected. The host output becomes:
Host started. Press Enter to terminate host.
End of CreateRecordSet(). RecordSets.Count = 1
Beginning of First(). RecordSets.Count = 1
... and then the client prints the customer names as expected, without errors.
So what am I missing? My understanding is that as long as I use the same ServiceReference (MyService) for both calls, then they should share the same static variables on the server if the server's InstanceContextMode is set to PerSession. Am I incorrect?
-Joe