Partager via


Gérer le contexte du service de données (WCF Data Services)

La classe DataServiceContext encapsule des opérations prises en charge sur un service de données spécifié. Même si les services OData sont sans état, ce n'est pas le cas du contexte. Par conséquent, vous pouvez utiliser la classe DataServiceContext pour conserver l'état sur le client entre des interactions avec le service de données afin de prendre en charge des fonctionnalités telles que la gestion des changements. Cette classe gère également des identités et suit les modifications.

Options de fusion et résolution d'identité

Lorsqu'un objet DataServiceQuery<TElement> est exécuté, les entités du flux de réponse sont matérialisées en objets. Pour plus d'informations, consultez Matérialisation d'objets (WCF Data Services). La façon dont les entrées d'un message de réponse sont matérialisées en objets dépend de la résolution d'identité et de l'option de fusion sous laquelle la requête a été exécutée. Lorsque plusieurs requêtes ou demandes de chargement sont exécutées dans l'étendue d'un objetDataServiceContext unique, le client Services de données WCF ne suit qu'une seule instance d'un objet qui a une valeur de clé spécifique. Cette clé, utilisée pour effectuer la résolution d'identité, identifie une entité de façon unique.

Par défaut, le client ne matérialise qu'une seule entrée du flux de réponse en un objet pour les entités qui ne sont pas déjà suivies par l'objet DataServiceContext. Cela signifie que les modifications apportées à des objets déjà dans le cache ne sont pas remplacées. Ce comportement est contrôlé en spécifiant une valeur MergeOption pour les requêtes et les opérations de chargement. Cette option est spécifiée en définissant la propriété MergeOption sur l'objet DataServiceContext. La valeur de l'option de fusion par défaut est AppendOnly. Cela ne matérialise les objets que pour les entités qui ne sont pas déjà suivies, ce qui signifie que les objets existants ne sont pas remplacés. Il existe un autre moyen d'empêcher que les modifications apportées aux objets sur le client ne soient remplacées par les mises à jour provenant du service de données. Il consiste à spécifier PreserveChanges. Lorsque vous spécifiez OverwriteChanges, les valeurs des objets sur le client sont remplacées par les valeurs les plus récentes à partir des entrées du flux de réponse, même si les modifications ont déjà été apportées à ces objets. Lorsqu'une option de fusion NoTracking est utilisée, l'objet DataServiceContext ne peut pas transmettre au service de données les modifications apportées aux objets clients. Avec cette option, les modifications sont toujours remplacées par les valeurs du service de données.

Gestion de l'accès concurrentiel

OData prend en charge l'accès concurrentiel optimiste qui permet au service de données de détecter des conflits de mise à jour. Le fournisseur de services de données peut être configuré de telle façon que le service de données recherche les modifications apportées aux entités à l'aide d'un jeton d'accès concurrentiel. Ce jeton comprend une ou plusieurs propriétés d'un type d'entité qui sont validées par le service de données afin de déterminer si une ressource a changé. Les jetons d'accès concurrentiel, qui sont inclus dans l'en-tête eTag des demandes et des réponses du service de données, sont gérés pour vous par le client Services de données WCF. Pour plus d'informations, consultez Mise à jour du service de données (WCF Data Services).

L'objet DataServiceContext suit les modifications apportées aux objets signalées manuellement à l'aide des méthodes AddObject, UpdateObject et DeleteObject, ou à l'aide d'un objet DataServiceCollection<T>. Lorsque la méthode SaveChanges est appelée, le client renvoie les modifications au service de données. La méthode SaveChanges peut échouer lorsque les modifications apportées aux données dans le client entrent en conflit avec les modifications du service de données. Lorsque cela se produit, vous devez redemander la ressource de l'entité pour recevoir les données de mise à jour. Pour supprimer les modifications du service de données, exécutez cette requête à l'aide de l'option de fusion PreserveChanges. Lorsque vous rappelez la méthodeSaveChanges, les modifications conservées sur le client sont rendues persistantes sur le service de données à condition que d'autres modifications n'aient pas déjà été apportées à la ressource dans le service de données.

Enregistrement des modifications

Les modifications sont suivies dans l'instance DataServiceContext mais ne sont pas envoyées au serveur immédiatement. Une fois que vous avez terminé d'effectuer les modifications requises pour une activité spécifiée, appelez SaveChanges afin de soumettre toutes les modifications au service de données. Un objet DataServiceResponse est retourné au terme de l'opération SaveChanges. L'objet DataServiceResponse inclut une séquence d'objets OperationResponse qui, à leur tour, contiennent une séquence d'instances EntityDescriptor ou LinkDescriptor représentant les modifications qui ont été tentées ou rendues persistantes. Lorsqu'une entité est créée ou modifiée dans le service de données, EntityDescriptor inclut une référence à l'entité mise à jour, notamment les valeurs de propriété générées par le serveur, telles que la valeur ProductID générée dans l'exemple précédent. La bibliothèque cliente met automatiquement à jour l'objet .NET Framework avec ces nouvelles valeurs.

Pour les opérations d'insertion et de mise à jour qui ont abouti, la propriété d'état de l'objet EntityDescriptor ou LinkDescriptor associé à l'opération aura la valeur Unchanged et les nouvelles valeurs seront fusionnées à l'aide de OverwriteChanges.

Lorsqu'une opération d'insertion, de mise à jour ou de suppression échoue dans le service de données, l'entité conserve l'état qui était le sien avant l'appel de SaveChanges et la propriété Error de l'objet OperationResponse prend la valeur DataServiceRequestException qui contient les informations relatives à l'erreur. Pour plus d'informations, consultez Mise à jour du service de données (WCF Data Services).

Gestion des demandes

Le protocole OData offre de la flexibilité dans les comportements des demandes et des réponses provenant d'un service de données. La bibliothèque cliente vous permet de tirer parti de cette flexibilité en contrôlant comment votre application interagit avec le service de données.

Définition de l'en-tête Prefer pour les opérations de modification

Par défaut, une charge de message n'est retournée qu'en réponse à une demande POST de création d'une nouvelle entité. Dans ce cas, la nouvelle entité est retournée dans la charge utile. Cela signifie que lorsque les mises à jour sont appliquées aux objets, l'entité mise à jour n'est pas retournée dans la charge utile ou un message de réponse. Toutefois, le protocole OData affirme qu'un client peut utiliser l'en-tête Prefer pour demander une modification du comportement par défaut. L'en-tête Prefer d'une demande POST, PUT, PATCH OU MERGE est généré par le DataServiceContext selon la valeur du DataServiceResponsePreference défini dans la propriété AddAndUpdateResponsePreference. Le tableau suivant indique les options d'en-tête Prefer et les comportements de réponse associés :

Valeur de l'en-tête Prefer

Valeur AddAndUpdateResponsePreference

Comportement de réponse

Non inclus dans la demande. Il s'agit du comportement par défaut.

None

Une charge de réponse n'est retournée pour les demandes POST et pas pour les demandes PUT, PATCH et MERGE.

return-content

IncludeContent

Une charge de réponse est retournée pour toutes les demandes de modification.

return-no-content

NoContent

Aucune charge utile de réponse n'est retournée pour toutes les demandes. Pour une demande POST, le service de données inclut également un en-tête DataServiceId dans la réponse. Cet en-tête est utilisé pour communiquer la valeur de clé de l'entité nouvellement créée.

Notes

Même lorsque le service de données prend en charge une version du protocole OData qui prend en charge l'en-tête Prefer, un service de données peut choisir de ne pas honorer ces types de préférences de traitement des demandes.

Définition de la méthode HTTP pour les mises à jour

Par défaut, la bibliothèque cliente .NET Framework envoie des mises à jour aux entités existantes sous forme de demandes MERGE. Dans OData, Une demande MERGE met à jour les propriétés sélectionnées de l'entité. Toutefois, le client inclut systématiquement toutes les propriétés dans la demande MERGE, même celles qui n'ont pas changé. Le protocole OData prend également en charge l'envoi de requêtes PUT et PATCH pour mettre à jour des entités. Dans une demande PUT, une entité existante est essentiellement remplacée par une nouvelle instance de l'entité avec les valeurs de propriété du client. Les demandes PATCH sont traitées de la même façon que les demandes MERGE, mais PATCH est une action HTTP standard tandis que MERGE est une action définie par OData. Ce comportement de mise à jour est spécifié en fournissant soit la valeur ReplaceOnUpdate, pour utiliser des demandes PUT, soit la valeur PatchOnUpdate, pour utiliser des demandes PATCH, comme options en appelant SaveChanges(SaveChangesOptions).

Notes

Une demande PUT va se comporter différemment d'une demande MERGE ou PATCH lorsque le client ne connaît pas toutes les propriétés de l'entité.Cela peut se produire lors de la projection d'un type d'entité dans un nouveau type, sur le client.C'est également le cas lorsque de nouvelles propriétés ont été ajoutées à l'entité dans le modèle de données du service et la propriété IgnoreMissingProperties sur le DataServiceContext est définie sur true pour ignorer ces erreurs de mappage du client.Dans ces cas, une demande PUT va réinitialiser toutes les propriétés inconnues sur le client selon leurs valeurs par défaut.

Tunneling de publication

Par défaut, la bibliothèque cliente envoie des demandes de création, lecture, mise à jour et suppression à un service OData à l'aide des méthodes HTTP correspondantes de POST, GET, PUT/MERGE/PATCH et DELETE. Cela confirme les principes de base de REST (Representational State Transfer). Toutefois, toutes les implémentations de serveur Web ne prennent pas en charge la totalité des méthodes HTTP. Dans certains cas, les méthodes prises en charge peuvent être limitées à GET et POST. Cela peut se produire lorsqu'un intermédiaire, comme un pare-feu, bloque les demandes par certaines méthodes. Étant donné que les méthodes GET et POST sont le plus souvent prises en charge, OData offre un moyen d'exécuter toutes les méthodes non prises en charge HTTP à l'aide d'une demande POST. Appelé tunneling de méthode ou tunneling de publication, ce moyen permet à un client d'envoyer une demande POST avec la méthode réelle spécifiée dans l'en-tête X-HTTP-Method personnalisé. Pour activer le tunneling de publication pour les demandes, définissez la propriété UsePostTunneling sur l'instance DataServiceContext sur true.

Résolution de l'URI de base des jeux d'entités

Par défaut, le client suppose que tous les jeux d'entités, également appelés collections, partagent le même URI de base. Cet URI de base est défini par la propriété BaseUri dans DataServiceContext. Toutefois, le protocole OData autorise un service de données à exposer des jeux d'entités sous la forme de flux avec différents URI de base. Pour pouvoir gérer les jeux d'entités avec des URI de base, le client vous permet de stocker un délégué avec DataServiceContext qui peut être utilisé pour résoudre les URI de base de différents jeux d'entités. Ce délégué est une méthode qui prend une chaîne (le nom du jeu d'entités) et retourne Uri (l'URI de base pour le jeu d'entités spécifié). Ce programme de résolution est enregistré avec DataServiceContext par assignation à la propriété ResolveEntitySet. Un exemple d'implémentation du programme de résolution peut, lorsque le contexte est créé, lire les informations sur les collections retournées par la racine du service de données et enregistrer les valeurs d'URI de base pour chaque collection d'un dictionnaire. Ce dictionnaire peut ensuite être utilisé par le programme de résolution pour retourner l'URI pour un jeu d'entités spécifique. Pour un exemple plus complet, comprenant l'exemple de code, consultez la publication Programme de résolution de jeu d'entités.

Conditions requises pour le contrôle de version

Les comportements DataServiceContext ont les conditions requises pour le contrôle de version de protocole OData suivant :

  • La prise en charge de l'en-tête Prefer et des demandes PATCH requièrent que le client et le service de données prennent en charge les versions 3.0 et ultérieures du protocole OData.

  • La prise en charge des programmes de résolution de jeu d'entités requiert la version de la bibliothèque cliente Services de données WCF incluse avec la version finale de Data Framework ou une version ultérieure.

Pour plus d'informations, consultez Contrôle de version d'un service de données (WCF Data Services).