1

データのセットを生成し、クライアントがそれらを作成し、それらをナビゲートし、それらからデータを取得できるようにする WCF アプリケーションを作成しています。データは、サービス クラスの静的変数に格納されます。特に、GUID 文字列をキーとして使用して、辞書に格納されます。

サービス クラスのインスタンス化モードを PerSession に設定していますが、これは私の知る限りうまくいくはずです。クライアントは CreateRecordSet という関数を呼び出します。この関数はエントリを辞書に追加し、キー文字列を返します。次に、クライアントは First() という関数を呼び出します。この関数は、データ セットの最初のレコードを取得する必要があります。ただし、これを試みると、ディクショナリにはエントリが含まれなくなります。

不思議なことに、インスタンス化モードを Single に設定すると、問題なく動作します。しかし、PerSession に設定すると、2 つの呼び出しの間で辞書が失われるように見えます。これは、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

...そして、クライアントはエラーなしで期待どおりに顧客名を出力します。

それで、私は何が欠けていますか?私の理解では、サーバーの InstanceContextMode が PerSession に設定されている場合、両方の呼び出しに同じ ServiceReference (MyService) を使用している限り、サーバー上で同じ静的変数を共有する必要があります。私は間違っていますか?

-ジョー

4

0 に答える 0