次の方法で共有


セッションの使用

Windows Communication Foundation (WCF) アプリケーションでは、セッションがメッセージのグループを相互に関連付けて通信を行います。WCF セッションは、ASP.NET アプリケーションで使用できるセッション オブジェクトとは異なるものであり、サポートされる動作と制御する方法が異なります。ここでは、WCF アプリケーションのセッションで有効になる諸機能とそれらの使用方法について説明します。

Windows Communication Foundation アプリケーションのセッション

サービス コントラクトでセッションが必要であると指定されている場合、すべての呼び出し (つまり、呼び出しをサポートする基本的なメッセージ交換) を同じメッセージ交換の一部にする必要があります。セッションが許可されるが必須ではないコントラクトの場合、クライアントは、接続した後にセッションを確立できます。また、セッションを確立しないままにしておくこともできます。セッションが終了したのに、同じチャネルでメッセージが送信されると、例外がスローされます。

WCF セッションには、主に次のような概念的特徴があります。

  • 呼び出し側アプリケーション (WCF クライアント) によって明示的に開始および終了される。

  • セッション中に配信されたメッセージは、受信された順に処理される。

  • セッションはメッセージのグループを相互に関連付けて通信を行う。関連付けにはさまざまな種類があります。たとえば、あるセッション ベースのチャネルでは、共有ネットワーク接続に基づいてメッセージが相互に関連付けられる一方、別のセッション ベースのチャネルでは、メッセージ本文にある共有タグに基づいてメッセージが相互に関連付けられます。セッションから派生可能な機能は、相互関連付けの性質によって異なります。

  • WCF セッションに関連付けられた一般的なデータ ストアはありません。

ASP.NET アプリケーションの System.Web.SessionState.HttpSessionState クラスに精通している場合は、この種のセッションと WCF セッションの間に次のような相違があることがわかります。

  • ASP.NET セッションは、常にサーバーによって開始される。

  • ASP.NET セッションは、暗黙的に順序付けされない。

  • ASP.NET セッションは、要求全体について一般的なデータ ストレージ機構を提供する。

このトピックでは、次の項目について説明します。

  • サービス モデル レイヤーにおいてセッション ベースのバインディングを使用する場合の既定の実行動作。

  • WCF のセッション ベースのシステム提供バインディングが提供する機能の種類。

  • セッションの要件を宣言するコントラクトの作成方法。

  • セッションの作成と終了、およびセッションとサービス インスタンスの関係を理解し、制御する方法。

セッションを使用した既定の実行動作

セッションの開始を試みるバインディングは、セッション ベースのバインディングと呼ばれます。サービス コントラクトで、セッション ベースのバインディングを要求、許可、または拒否するように指定するときは、サービス コントラクト インターフェイス (またはクラス) の System.ServiceModel.ServiceContractAttribute.SessionMode プロパティを System.ServiceModel.SessionMode 列挙値に設定します。このプロパティの既定値は Allowed であり、その場合、クライアントが WCF サービス実装でセッション ベースのバインディングを使用すると、サービスは、提供されるセッションを確立して使用します。

WCF サービスがクライアント セッションを受け入れると、既定で次の機能が有効になります。

  1. WCF クライアント オブジェクト間のすべての呼び出しは、同一のサービス インスタンスによって処理されます。

  2. さまざまなセッション ベースのバインディングによって追加機能が提供されます。

システム指定のセッションの種類

セッション ベースのバインディングは、サービス インスタンスと特定のセッションとの既定の関連付けをサポートします。ただし、前のセッション ベースのインスタンス化制御を有効にすることに加えて、セッション ベースのバインディングごとにサポートされる機能も異なります。

WCF には、次の種類のセッション ベースのアプリケーション動作が用意されています。

  • 2 者間の通信で特定のセキュリティ保護されたメッセージ交換について両者の合意が成立している場合、System.ServiceModel.Channels.SecurityBindingElement は、セキュリティ ベースのセッションをサポートします。詳細については、次のトピックを参照してください。 サービスのセキュリティ保護.たとえば、セキュリティ セッションと信頼できるセッションの両方のサポートを含む System.ServiceModel.WSHttpBinding バインディングは、既定では、メッセージを暗号化してデジタル署名を行うセキュリティで保護されたセッションのみを使用します。

  • System.ServiceModel.NetTcpBinding バインディングは、TCP/IP ベースのセッションをサポートしており、すべてのメッセージがソケット レベルの接続によって関連付けられます。

  • WS-ReliableMessaging 仕様を実装する System.ServiceModel.Channels.ReliableSessionBindingElement 要素は、メッセージを順番に 1 回だけ配信するように構成できる、信頼できるセッションをサポートします。これにより、メッセージ交換時にメッセージが複数のノードを通過する場合でもメッセージが受信されます。詳細については、次のトピックを参照してください。 信頼できるセッション.

  • System.ServiceModel.NetMsmqBinding バインディングは、MSMQ データグラム セッションを提供します。詳細については、次のトピックを参照してください。 Windows Communication Foundation のキュー.

SessionMode プロパティを設定しても、コントラクトが必要とするセッションの種類は指定されず、コントラクトがセッションを必要とすることだけが指定されます。

セッションを必要とするコントラクトの作成

セッションを必要とするコントラクトを作成するのは、サービス コントラクトで宣言する操作のグループをすべて同じセッション内で実行し、メッセージを順番に配信する必要がある場合です。サービス コントラクトが必要とするセッションのサポート レベルをアサートするには、サービス コントラクト インターフェイスまたはクラスの System.ServiceModel.ServiceContractAttribute.SessionMode プロパティを System.ServiceModel.SessionMode 列挙値に設定して以下を指定します。

  • コントラクトがセッションを必要とするかどうか。

  • コントラクトで、クライアントによるセッションの確立を許可するかどうか。

  • コントラクトでセッションを禁止するかどうか。

ただし、SessionMode プロパティを設定しても、コントラクトが必要とするセッション ベースの動作の種類は指定されません。このプロパティは、サービスの (通信チャネルを作成する) 構成済みバインディングが、サービスの実装時にセッションを確立する、確立しない、または確立できるかを実行時に確認するよう WCF に指示します。ここでもバインディングは、選択する任意の種類のセッション ベースの動作 (セキュリティ セッション、トランスポート セッション、信頼できるセッション、またはこれらの一定の組み合わせ) によってこの要件を満たすことができます。正確な動作は、選択した System.ServiceModel.SessionMode 値によって決まります。サービスの構成済みバインディングが SessionMode の値に一致しない場合は、例外がスローされます。セッションをサポートするバインディングと、それが作成するチャネルは、セッション ベースのバインディングまたはチャネルと呼ばれます。

次のサービス コントラクトは、ICalculatorSession のすべての操作をセッション内で交換する必要があることを指定しています。Equals メソッドを除き、どの操作も呼び出し元に値を返しません。ただし、Equals メソッドはパラメーターを受け取らないため、データが既に他の操作に渡されているセッション内では、ゼロ以外の値しか返すことができません。このコントラクトでは、セッションが正常に機能する必要があります。特定のクライアントに関連付けられているセッションがないと、サービス インスタンスは、そのクライアントが以前に送信したデータを知ることができません。

<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession

    <OperationContract(IsOneWay:=True)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True)> _
    Sub DivideBy(ByVal n As Double)
    <OperationContract()> _
    Function Equal() As Double
End Interface
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
    [OperationContract(IsOneWay=true)]
    void Clear();
    [OperationContract(IsOneWay = true)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true)]
    void DivideBy(double n);
    [OperationContract]
    double Equals();
}

サービスがセッションを許可した場合は、クライアントがセッションを開始するとセッションが確立され、使用されますが、許可しない場合は、セッションが確立されません。

セッションとサービス インスタンス

WCF で既定のインスタンス化動作を使用した場合は、WCF クライアント オブジェクト間のすべての呼び出しが同じサービス インスタンスによって処理されます。そのため、アプリケーション レベルでは、セッションは、ローカル呼び出し動作と同様のアプリケーション動作を有効にすると考えることができます。たとえば、ローカル オブジェクトを作成するときは、次のような流れになります。

  • コンストラクターが呼び出されます。

  • この後に、WCF クライアント オブジェクト参照に対して行われる呼び出しは、すべて同じオブジェクト インスタンスによって処理されます。

  • オブジェクト参照が破棄されると、デストラクターが呼び出されます。

既定のサービス インスタンス動作を使用している限り、セッションでは、クライアントとサービス間で同様の動作が有効になります。サービス コントラクトがセッションを必要としたり、サポートしたりする場合は、IsInitiating プロパティと IsTerminating プロパティを設定することで、1 つ以上のコントラクト操作をセッションの開始または終了としてマークできます。

開始操作は、新しいセッションの最初の操作として呼び出す必要がある操作です。開始操作以外の操作は、少なくとも 1 つの開始操作が呼び出された後にしか呼び出すことはできません。そのため、サービス インスタンスの開始に適した入力をクライアントから取得するように設計された開始操作を宣言することで、サービスに対する一種のセッション コンストラクターを作成できます (ただし、状態はセッションに関連付けられ、サービス オブジェクトに関連付けられません)。

終了操作は、開始操作とは逆に、既存のセッションの最終メッセージとして呼び出す必要がある操作です。既定では、WCF は、サービスが関連付けられているセッションが閉じられた後に、サービス オブジェクトとそのコンテキストを再利用します。そのため、サービス インスタンスの終了に適した関数を実行するように設計された終了操作を宣言することで、一種のデストラクターを作成できます。

ms733040.note(ja-jp,VS.100).gif注 :
既定の動作は、ローカルのコンストラクターとデストラクターに似ていますが、あくまで似ているだけです。任意の WCF サービス操作を開始操作または終了操作として使用できます。また、両方を同時に兼ねることもできます。さらに既定では、開始操作は、任意の順序で何回でも呼び出すことができます。そのため、System.ServiceModel.InstanceContext オブジェクトを操作することでサービス インスタンスの有効期間を明示的に制御しない限り、セッションが確立されインスタンスに関連付けられた後に、追加セッションは作成されません。また、状態はセッションに関連付けられ、サービス オブジェクトには関連付けられません。

たとえば、前の例で使用した ICalculatorSession コントラクトで、WCF クライアント オブジェクトが、他の操作に先立って最初に Clear 操作を呼び出す必要があり、さらにこの WCF クライアント オブジェクトとのセッションが、Equals 操作を呼び出したときに終了する必要があるとします。これらの要件を適用するコントラクトを次のコード例に示します。セッションを開始するには最初に Clear を呼び出す必要があり、また Equals を呼び出すとこのセッションは終了します。

<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required)> _
Public Interface ICalculatorSession

    <OperationContract(IsOneWay:=True, IsInitiating:=True, IsTerminating:=False)> _
    Sub Clear()
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub AddTo(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub SubtractFrom(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub MultiplyBy(ByVal n As Double)
    <OperationContract(IsOneWay:=True, IsInitiating:=False, IsTerminating:=False)> _
    Sub DivideBy(ByVal n As Double)
    <OperationContract(IsInitiating:=False, IsTerminating:=True)> _
    Function Equal() As Double
End Interface
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
    [OperationContract(IsOneWay=true, IsInitiating=true, IsTerminating=false)]
    void Clear();
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void AddTo(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void SubtractFrom(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void MultiplyBy(double n);
    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void DivideBy(double n);
    [OperationContract(IsInitiating = false, IsTerminating = true)]
    double Equals();
}

サービスは、クライアントとのセッションを開始しません。WCF クライアント アプリケーションでは、セッション ベースのチャネルの有効期間とセッション自体の有効期間の間には直接的な関係があります。そのため、クライアントは、新しいセッション ベースのチャネルを作成することによって新しいセッションを作成し、セッション ベースのチャネルを正常に閉じることによって、既存のセッションを破棄します。クライアントは、次のいずれかを呼び出してサービス エンドポイントとのセッションを開始します。

通常は、クライアントが次のいずれかを呼び出して、サービス エンドポイントとのセッションを終了します。

  • System.ServiceModel.ChannelFactory.CreateChannel の呼び出しによって返されるチャネルの System.ServiceModel.ICommunicationObject.Close

  • Svcutil.exe によって生成された WCF クライアント オブジェクトの System.ServiceModel.ClientBase.Close

  • いずれかの型の WCF クライアント オブジェクトの終了操作 (既定では、終了操作はありません。コントラクトで終了操作を明示的に指定する必要があります)。最初の操作が呼び出されると、WCF クライアント オブジェクトが自動的にチャネルを開き、セッションを開始します。

たとえば、「方法 : セッションを必要とするサービスを作成する」のほかにも「既定のサービスの動作」や「インスタンス化」のサンプルを参照してください。

クライアントとセッション詳細情報、「クライアントを使用したサービスへのアクセス」を参照してください。

InstanceContext 設定と対話するセッション

コントラクト内の SessionMode 列挙と、チャネルと特定のサービス オブジェクト間の関連付けを制御する System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode プロパティの間には相互作用があります。詳細については、次のトピックを参照してください。 セッション、インスタンス化、および同時実行.

InstanceContext オブジェクトの共有

ユーザーが自ら関連付けを行うことにより、どの InstanceContext オブジェクトに、どのセッション ベースのチャネルまたは呼び出しを関連付けるかを制御することもできます。詳細な例については、「InstanceContextSharing」を参照してください。

セッションとストリーミング

大量のデータを転送する場合、メッセージ全体をメモリ内でバッファー化および処理するという既定の動作の代わりに、WCF のストリーミング転送モードを使用できます。セッション ベースのバインディングでストリーミングを呼び出すと、予期しない動作を引き起こすことがあります。すべてのストリーミング呼び出しは単一のチャネル (データグラム チャネル) を通じて行われますが、このチャネルは使用されるバインディングがセッションを使用するように構成されている場合であっても、セッションをサポートしません。セッション ベースのバインディングによって複数のクライアントが同一のサービス オブジェクトに対してストリーミング呼び出しを行う場合、このサービス オブジェクトの同時実行モードが単一に設定され、インスタンス コンテキスト モードが PerSession に設定されていると、すべての呼び出しがこのデータグラム チャネルを通過する必要があるため、同時に処理される呼び出しは 1 つに限られることになります。そのため、1 つ以上のクライアントがタイムアウトとなる可能性があります。サービス オブジェクトの InstanceContextModePerCall に設定するか、または同時実行モードを複数に設定することで、この問題を回避できます。

ms733040.note(ja-jp,VS.100).gif注 :
この場合、利用可能になる "セッション" は 1 つしかないため、MaxConcurrentSessions は効力を失います。

参照

リファレンス

IsInitiating
IsTerminating