1

Silverlightアプリケーションで使用しているセルフホストのWCFサービスがあります。IDictionaryオブジェクトにユーザーGUIDのリストを保存しようとしています。ユーザーがサービスにアクセスするたびに、ユーザーの日時が更新されるため、アクティブな「セッション」を持っているユーザーを追跡できます。問題は、私がサービスにアクセスするたびに、リストが空になることです。各soapリクエストの値を落としているように見えますか?

複数のサービスリクエストで利用できるセルフホストサービスに情報を保存できますか?

前もって感謝します!

4

4 に答える 4

2

インスタンスごとです。つまり、デフォルトではセッションレスです。

これを見てください

サービスコントラクトがSystem.ServiceModel.ServiceContractAttribute.SessionModeプロパティをSystem.ServiceModel.SessionMode.Requiredに設定する場合、そのコントラクトは、すべての呼び出し(つまり、呼び出しをサポートする基になるメッセージ交換)が同じ会話の一部である必要があることを示しています。 。

于 2012-10-01T18:10:50.053 に答える
2

リクエストの間に物を保存する必要がある場合は、これらのリクエストを受信時に保存するための適切なロックを備えた静的ディクショナリを作成するか、この情報をデータベース(または他の外部ストア)に保存して確認する必要があります各メソッド呼び出しに存在します。これは、クライアントの要求ごとにサービスクラスがインスタンス化されるためです。

ユーザーがサービスにアクセスしたときにユーザーの日時を既に更新しているので、日時フィールドと比較して、これがアクティブユーザーであるかどうかを確認することをお勧めします。これには、すべての呼び出しで正確であるという利点があります(サービスが再起動されると、ディクショナリがデータベースと同期しなくなる可能性があります)。データベースには、同時実行性を処理するためのメカニズムがすでに用意されているため、シングルトンオブジェクトの周りに独自のロックソリューションをロールバックするのではなく、複雑さをデータストアにプッシュできます。

2番目のソリューションが十分に高速でない場合(アプリのプロファイルを作成し、それがボトルネックであると判断した場合)、他のオプションは、データベースの前にある種のキャッシュソリューションを使用して、データを最初にメモリでチェックしてから移動することです。データベースに。このキャッシュオブジェクトは、ディクショナリのように静的である必要があり、他のマルチスレッドアプリケーションと同じようにロックに関する落とし穴があります。

編集:このホストされたWCFサービスがSilverlightアプリケーションのユーザーのセッションストレージとして使用されており、データが外部データストアに保存されていない場合は、それらがアクティブであるかどうかの追跡がミッションクリティカルではないことを確認してください。このデータは、説明されているように正しいことを保証することはできません。

サービスに障害が発生して再起動する必要がある場合は、受け入れられた回答に基づいて(これはセルフホストであるため、障害が発生したイベントを監視することをお勧めします)、サービスホストを破棄し、新しいホストをインスタンス化する必要があります。Guidデータを保持できる唯一の方法は、再起動の間にサービスにリバウンドする場合です(ホストアプリ自体が再起動されないと仮定すると、これは別の問題です)。

private Dictionary<Guid,string> _session;

Service service = new Service(_session);
_serviceHost = new ServiceHost(service, GetUriMethodInHostApp());

これを外部に保存し、@marc_sが示唆するようにルックアップを実行することをお勧めします。その後、この複雑さはなくなります。

于 2012-10-01T18:18:33.640 に答える
1

を変更する必要がありますInstanceContextMode。これを行うには、次のコンパイラ指令をWCFクラスに追加します。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

これにより、WCFサービスが一種のシングルトンとして実行されます。WCFインスタンスコンテキストモードの詳細を参照してください

次に、シングルトンオブジェクトを使用してサービスホストを構築する必要があります。これは、私が似たようなことをしている実際の例のコードです。

            private ServiceHost serviceHost;

            if (serviceHost != null)
                serviceHost.Close();

            if (log.IsInfoEnabled)
                log.Info("Starting WCF service host for endpoint: " + ConfiguredWCFEndpoint);

            // Create our service instance, and add create a new service host from it
            ServiceLayer.TagWCFService service = new ServiceLayer.TagWCFService(ApplicationName,
                ApplicationDescription,
                SiteId,
                ConfiguredUpdateRateMilliseconds);

            serviceHost = new ServiceHost(service, new Uri(ConfiguredWCFEndpoint));

            // Open the ServiceHostBase to create listeners and start listening for messages.
            serviceHost.Open();

他の人が丁寧に指摘しているように、これがどのように機能するかをよく知らない場合、または特定のアプリケーションに適していない場合、これは「結果」をもたらす可能性があります。

于 2012-10-01T18:15:55.730 に答える
1

ロックやスレッドセーフな特定のコードを使用する必要がない場合は、NoSQLデータベースを使用して、MongoDBRavenDBなどのセッションデータを保存できます。

@marc_sのように、シングルトンモードを使用することは危険なことだと思います。独自のスレッドセーフなセッションメカニズムを作成するには、非常に注意する必要があります。

于 2012-10-01T18:31:02.657 に答える