我正在编写一个生成数据集的 WCF 应用程序,并允许客户端创建它们、浏览它们并从中检索数据。数据存储在服务类的静态变量中。特别是,它们存储在字典中,使用 GUID 字符串作为键。
我将服务类的实例化模式设置为 PerSession,据我所知应该可以工作。客户端调用一个名为 CreateRecordSet 的函数,该函数将一个条目添加到字典中并返回密钥字符串。然后客户端调用一个名为 First() 的函数,该函数应该检索数据集中的第一条记录。但是,当它尝试这样做时,字典不再包含任何条目。
奇怪的是,如果我将实例化模式设置为 Single,它工作正常。但是,如果我将它设置为 PerSession,它似乎会丢失两个调用之间的字典,如果我将它设置为 PerCall,我会预料到这一点。
这是接口定义:
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; }
}
}
这是服务类代码:
[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
}
这是客户端代码:
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();
}
如您所见,我在主机的控制台中添加了一些调试消息以显示字典的状态。这是主机的输出:
Host started. Press Enter to terminate host.
End of CreateRecordSet(). RecordSets.Count = 1
Beginning of First(). RecordSets.Count = 0
当然,当我尝试引用 RecordSets[setkey] 时,我在 First() 的下一行代码中遇到异常,因为 RecordSets 是空的。
如果我将行为更改为:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
...然后它按预期工作。主机输出变为:
Host started. Press Enter to terminate host.
End of CreateRecordSet(). RecordSets.Count = 1
Beginning of First(). RecordSets.Count = 1
...然后客户端按预期打印客户名称,没有错误。
那么我错过了什么?我的理解是,只要我对两个调用都使用相同的 ServiceReference (MyService),那么如果服务器的 InstanceContextMode 设置为 PerSession,它们应该在服务器上共享相同的静态变量。我不正确吗?
-乔