データ サービス コンテキストの管理 (WCF Data Services)

DataServiceContext クラスは、特定のデータ サービスに対してサポートされている操作をカプセル化します。 OData サービスはステートレスですが、コンテキストはステートレスではありません。 このため DataServiceContext クラスを使用すると、変更管理などの機能をサポートするためにデータ サービスとの対話操作間におけるクライアントの状態を保持できます。 このクラスは、ID の管理と変更の追跡も行います。

マージ オプションおよび ID 解決

DataServiceQuery<TElement> が実行されると、応答フィードのエンティティはオブジェクトに具体化されます。 詳細については、「オブジェクトの具体化 (WCF Data Services)」を参照してください。 応答メッセージのエントリがオブジェクトに具体化される方法は、ID 解決に基づいて実行され、クエリが実行された際のマージ オプションによって決まります。 複数のクエリまたは読み込み要求が単一の DataServiceContext のスコープで実行される場合、WCF Data Services クライアントは特定のキー値を持つオブジェクトの単一のインスタンスのみを追跡します。 このキーは、ID 解決の実行に使用され、エンティティを一意に識別します。

既定では、クライアントは DataServiceContext によってまだ追跡されていないエンティティのオブジェクトに応答フィードのエントリを具体化するだけです。 これは、既にキャッシュ内にあるオブジェクトに対する変更は上書きされないことを意味します。 この動作は、クエリおよび読み込み操作に MergeOption 値を指定することによって制御されます。 このオプションを指定するには、DataServiceContextMergeOption プロパティを設定します。 既定のマージ オプションの値は AppendOnly です。 この既定値を設定した場合、まだ追跡されていないエンティティのオブジェクトのみが具体化されます。これは、既存のオブジェクトが上書きされないことを意味します。 クライアントのオブジェクトに対する変更がデータ サービスからの更新によって上書きされないようにするもう 1 つの方法は、PreserveChanges を指定する方法です。 OverwriteChanges を指定した場合、クライアントのオブジェクトの値は、既に変更が加えられていても、応答フィードのエントリの最新の値によって置換されます。 NoTracking マージ オプションを使用する場合、DataServiceContext はクライアント オブジェクトに加えられた変更をデータ サービスに送信できません。 このオプションを使用すると、変更は常にデータ サービスの値によって上書きされます。

同時実行の管理

OData では、オプティミスティック同時実行制御がサポートされており、データ サービスで更新の競合を検出できます。 データ サービス プロバイダーは、データ サービスで同時実行トークンを使用してエンティティへの変更をチェックするように構成できます。 このトークンには、リソースが変更されているかどうかを決定するためにデータ サービスによって検証されるエンティティ型の 1 つ以上のプロパティが含まれています。 同時実行トークンは、データ サービスへの要求およびデータ サービスからの応答の eTag ヘッダーに含まれ、WCF Data Services クライアントによって管理されます。詳細については、「データ サービスの更新 (WCF Data Services)」を参照してください。

DataServiceContext は、AddObjectUpdateObject、および DeleteObject を使用して手動で報告しているか、または DataServiceCollection<T> によって報告されているオブジェクトへの変更を追跡します。 SaveChanges メソッドを呼び出すと、クライアントはデータ サービスに変更を送り返します。 SaveChanges は、クライアントでのデータ変更がデータ サービスでの変更と競合する場合に失敗する可能性があります。 このような状況が発生した場合、エンティティ リソースに対してクエリを再度実行し、更新データを受信する必要があります。 データ サービスの変更を上書きするには、PreserveChanges マージ オプションを使用してクエリを実行します。 SaveChanges を再度呼び出すと、データ サービスのリソースに対してその他の変更がまだ行われていない場合に限り、クライアントに保存されている変更がデータ サービスに永続化されます。

変更の保存

変更は、DataServiceContext インスタンスで追跡されますが、サーバーには直ちに送信されません。 指定されたアクティビティに対して必要な変更が完了した後、SaveChanges を呼び出して、すべての変更をデータ サービスに送信します。 SaveChanges 操作が完了した後、DataServiceResponse オブジェクトが返されます。 DataServiceResponse オブジェクトには、OperationResponse オブジェクトのシーケンスが含まれます。さらに、これらの各オブジェクトには、永続化または試行された変更を表す、EntityDescriptor インスタンスまたは LinkDescriptor インスタンスのシーケンスが含まれます。 データ サービス内でエンティティが作成または変更されると、前の例で生成された ProductID 値のようなサーバー生成のプロパティ値も含めて、更新されたエンティティへの参照が EntityDescriptor に含められます。 クライアント ライブラリは、これらの新しい値を持つように .NET Framework オブジェクトを自動的に更新します。

挿入操作と更新操作を適切に実行するため、その操作に関連付けられている EntityDescriptor オブジェクトまたは LinkDescriptor オブジェクトの状態プロパティが Unchanged に設定され、新しい値は OverwriteChanges を使用してマージされます。

データ サービス内で挿入、更新、または削除操作が失敗した場合、エンティティ状態は、SaveChanges が呼び出される前と同じままになり、OperationResponseError プロパティは、エラーに関する情報を含む DataServiceRequestException に設定されます。 詳細については、「データ サービスの更新 (WCF Data Services)」を参照してください。

要求の管理

OData プロトコルは、データ サービスとの間の要求と応答の動作に関する柔軟性を提供します。 クライアント ライブラリを使うと、アプリケーションがデータ サービスと対話する方法を制御することによってこのような柔軟性を活用できます。

変更操作のための Prefer ヘッダーの設定

既定では、新しいエンティティを作成するための POST 要求への応答でメッセージ ペイロードのみが返されます。 この場合、新しいエンティティがペイロードで返されます。 つまり、オブジェクトが更新されたとき、更新されたエンティティはペイロードまたは応答メッセージで返されません。 ただし、OData プロトコルでは、クライアントは Prefer ヘッダーを使用して、この既定の動作の変更を要求できます。 POST、PUT、PATCH、または MERGE 要求での Prefer ヘッダーは、DataServiceContext によって、AddAndUpdateResponsePreference プロパティに設定された DataServiceResponsePreference の値に基づいて生成されます。 Prefer ヘッダー オプションと関連の応答動作を次の表に示します。

Prefer ヘッダー値

AddAndUpdateResponsePreference の値

応答動作

要求に含まれていない (既定の動作)

None

応答ペイロードは、POST 要求に対してのみ返されます。PUT 要求、PATCH 要求、および MERGE 要求に対しては返されません。

return-content

IncludeContent

応答ペイロードは、すべての変更要求に対して返されます。

return-no-content

NoContent

応答ペイロードは、いずれの変更要求に対しても返されません。 POST 要求の場合、データ サービスは DataServiceId ヘッダーも応答に含めます。 このヘッダーは、新しく作成されたエンティティのキー値を伝達するために使用されます。

注意

データ サービスは、Prefer ヘッダーをサポートする OData プロトコルのバージョンをサポートしている場合でも、これらの種類の処理設定の要求を受け付けないことを選択できます。

更新用の HTTP メソッドの設定

既定では、更新は、.NET Framework クライアント ライブラリから既存のエンティティに MERGE 要求として送信されます。 OData では、MERGE 要求でエンティティの選択されたプロパティが更新されますが、クライアントは、常に、変更されていないプロパティを含むすべてのプロパティを MERGE 要求に含めます。 OData プロトコルは、エンティティを更新する PUT 要求および PATCH 要求の送信もサポートしています。 PUT 要求では、既存のエンティティが、クライアントからのプロパティ値を含むエンティティの新しいインスタンスによって本質的に置き換えられます。 PATCH 要求は、MERGE 要求と同じ方法で処理されます。MERGE が OData によって定義されるのに対し、PATCH は標準の HTTP アクションです。 この更新動作を指定するには、SaveChanges(SaveChangesOptions) を呼び出すときのオプションとして、PUT 要求を使用する ReplaceOnUpdate 値または PATCH 要求を使用する PatchOnUpdate を指定します。

注意

クライアントがエンティティの一部のプロパティを認識していない場合、PUT 要求は MERGE 要求または PATCH 要求とは異なる動作になります。この状況は、クライアントでエンティティ型を新しい型に射影する場合に発生することがあります。また、新しいプロパティがサービス データ モデルのエンティティに追加されており、このようなクライアントのマッピング エラーを無視するように DataServiceContextIgnoreMissingProperties プロパティが true に設定されている場合にも発生することがあります。この場合、PUT 要求では、クライアントが認識していないすべてのプロパティが既定値にリセットされます。

POST トンネリング

既定では、クライアント ライブラリは、作成、読み取り、更新、および削除要求を、POST、GET、PUT/MERGE/PATCH、および DELETE の対応する HTTP メソッドを使用して、OData サービスに送信します。 これは、Representational State Transfer (REST) の基本原則に沿った動作です。 ただし、すべての Web サーバー実装で HTTP メソッドの完全なセットがサポートされるとは限りません。 場合によっては、サポートされているメソッドが GET と POST のみに制限されていることもあります。 このような状況は、ファイアウォールのような仲介物が特定のメソッドの要求をブロックしている場合に発生します。 GET メソッドと POST メソッドは一般的にサポートされているメソッドであるため、OData では、サポートされていない HTTP メソッドを POST 要求を使用して実行する方法を規定しています。 メソッド トンネリングまたは POST トンネリングと呼ばれるこの方法を使うと、クライアントは、カスタムの X-HTTP-Method ヘッダーに実際のメソッドが指定された POST 要求を送信できます。 要求の POST トンネリングを有効にするには、DataServiceContext インスタンスの UsePostTunneling プロパティを true に設定します。

エンティティ セットのベース URI の解決

既定では、クライアントは、すべてのエンティティ セット ("コレクション" とも呼ばれます) が同じベース URI を共有することを前提としています。 このベース URI は、DataServiceContextBaseUri プロパティによって定義されます。 ただし、OData プロトコルでは、データ サービスは、エンティティ セットを異なるベース URI を持つフィードとして公開できます。 異なるベース URI を持つエンティティ セットを処理できるようにするために、クライアントでは、さまざまなエンティティ セットのベース URI を解決するために使用できるデリゲートを DataServiceContext に登録できます。 このデリゲートは、文字列 (エンティティ セット名) を受け取って Uri (指定されたエンティティ セットのベース URI) を返すメソッドです。 このリゾルバーは、ResolveEntitySet プロパティに割り当てることによって DataServiceContext に登録されます。 リゾルバーの実装例として、コンテキストが作成されたときに、データ サービス ルートから返されたコレクションに関する情報を読み取り、各コレクションのベース URI 値をディクショナリに格納します。 リゾルバーは、特定のエンティティ セットの URI を返すためにこのディクショナリを使うことができます。 サンプル コードを含むより完全な例については、ブログの記事「エンティティ セット リゾルバー」を参照してください。

バージョン管理の要件

DataServiceContext の動作には、次に示す OData プロトコルのバージョン管理の要件があります。

  • Prefer ヘッダーと PATCH 要求をサポートするには、クライアントとデータ サービスの両方でバージョン 3.0 以降の OData プロトコルがサポートされている必要があります。

  • エンティティ セット リゾルバーをサポートするには、Data Framework リリース以降のバージョンに含まれている WCF Data Services クライアント ライブラリが必要です。

詳細については、「データ サービスのバージョン管理 (WCF Data Services)」を参照してください。