Données

Cette section indiquent comment les Services RIA WCF traitent les scénarios exigeant de modéliser des données, de vérifier la validité des données et d'assurer l'accès concurrentiel aux données. Quand vous fournissez une interface de mise à jour, de suppression ou de création de données à partir du client d'une application Internet riche (RIA), vous devez fréquemment modéliser des relations de données complexes et vous assurer que les données provenant de l'utilisateur sont valides et à jour par rapport aux données de la source de données, avant de valider les modifications des données.

Généralement, vous utilisez l'Entity Data Model ou LINQ to SQL pour modéliser les données existant dans une base de données relationnelle. Cependant, vous n'êtes pas obligé d'utiliser une base de données dans un projet Services RIA . Vous pouvez utiliser tout type d'objet pour stocker des données. Le code dans le projet client qui facilite les opérations de données ne dépend pas de la source de données car il ignore en fait la technologie d'accès aux données ou le schéma qu'utilise la couche intermédiaire.

Relations de données

Les Services RIA fournissent des fonctionnalités qui vous permettent d'interagir avec des relations de données complexes, telles que, les modèles hiérarchiques, les modèles d'héritage polymorphes, les modèles de présentation consolidant des valeurs fournies par de nombreuses entités et les modèles incluant des valeurs fournies par plusieurs services de domaine. Le modèle hiérarchique représente une relation composée parent-enfant, par ex. entre Order et OrderDetails, ou une relation récursive, par ex. un modèle Employee incluant un champ pour un ManagerID qui pointe sur une autre entité du modèle Employee. Pour plus d'informations, consultez Hiérarchies de composition.

Dans un modèle d'héritage, vous pouvez représenter une structure de données qui inclut une entité Customer et deux entités qui en dérivent : PublicSectorCustomer et PrivateSectorCustomer. À l'aide des opérations de domaine, vous pouvez interroger et mettre à jour les types. Pour plus d'informations, consultez Héritage dans les modèles de données.

La prise en charge des types complexes de non-entité a été ajoutée dans les Services RIA V1.0 SP1. Spécifiquement, la prise en charge est fournie pour les codegen, les métadonnées, la validation profonde, le suivi des modifications, les sessions de modification et les paramètres de type complexes. Cela signifie que les types personnalisés, tels qu'Address, peuvent maintenant être utilisés comme propriétés ou paramètres de l'entité dans les méthodes DomainService ou retourner des valeurs depuis ces mêmes méthodes. Pour plus d'informations, consultez les rubriques Types complexes.

La prise en charge du partage d'une entité avec plusieurs services de domaine a été ajoutée dans les Services RIA V1.0 SP1. Elle apporte la flexibilité nécessaire pour segmenter vos classes DomainService de façon plus logique. Pour plus d'informations, consultez la rubrique Entités partagées.

Dans un modèle de présentation, vous pouvez générer des types pour la couche de présentation qui ne sont pas liés directement à la structure des tables de la source de données. Par exemple, vous pouvez générer un type de données nommé CustomerPresentation basé sur des classes de données pour les tables Customer, CustomerAddress et Address. Dans le type de présentation, vous regroupez uniquement les valeurs qui sont pertinentes pour la couche de présentation. Si des modifications sont effectuées dans le référentiel des données, vous pouvez modifier uniquement le type de présentation et ne pas mettre à jour l'application de code client qui interagit avec les données. Les Services RIA vous permettent de mettre à jour les données via le type de présentation. Pour plus d'informations, consultez Modèles de présentation.

Enfin, dans votre application, vous aurez peut être besoin d'afficher des données provenant de diverses sources de données ou d'exposer une entité unique à plusieurs services de domaine. Les Services RIA rendent ce scénario possible en prenant en charge des références entre des entités de types DomainContext divers. Par exemple, un site Web d'e-commerce peut avoir besoin d'intégrer des données provenant de son système de traitement des commandes avec des produits provenant d'un service de domaine tiers. Pour plus d'informations, consultez Procédure pas à pas : Partage d'entités entre plusieurs services de domaine.

Annotations et validation de données

Lorsque vous utilisez des classes de données dans votre application Services RIA , vous pouvez appliquer des attributs à la classe ou aux membres qui spécifient des règles de validation, indiquent le mode d'affichage des données et définissent les relations entre classes d'entité. L'espace de noms System.ComponentModel.DataAnnotations contient les classes utilisées comme attributs de données. En appliquant ces attributs à la classe de données ou au membre, vous centralisez la définition des données et vous n'avez pas à réappliquer les mêmes règles à plusieurs emplacements. Les attributs d'annotation des données sont organisés en trois catégories : attributs de validation, attributs d'affichage et attributs de modélisation de données. Pour plus d'informations, consultez Utilisation d'annotations de données pour personnaliser des classes de données et Procédure : Valider des données. Pour la validation, vous pouvez utiliser les attributs suivants :

  1. DataTypeAttribute

  2. RangeAttribute

  3. RegularExpressionAttribute

  4. RequiredAttribute

  5. StringLengthAttribute

  6. CustomValidationAttribute

Lorsque vous utilisez des classes de données automatiquement générées, telles qu'un Entity Data Model ou LINQ to SQL, vous n'appliquez pas les attributs directement aux classes générées, parce que les attributs seront perdus à la prochaine régénération de la classe. Vous créez plutôt une classe de métadonnées pour la classe de données et vous appliquez les attributs à la classe de métadonnées. Une classe de métadonnées est une classe partielle qui est désignée à partir de la classe de données comme type de métadonnées. Pour plus d'informations, consultez Procédure : Ajouter des classes de métadonnées.

L'exemple suivant montre une classe de métadonnées avec des attributs RoundtripOriginalAttribute, RequiredAttribute, StringLengthAttribute et ExcludeAttribute appliqués à certaines des propriétés.

<MetadataTypeAttribute(GetType(Address.AddressMetadata))>  _
Partial Public Class Address
    
    Friend NotInheritable Class AddressMetadata
        
        'Metadata classes are not meant to be instantiated.
        Private Sub New()
            MyBase.New
        End Sub
        
        Public AddressID As Integer

        <Required()> _
        <StringLength(60)> _
        <RoundtripOriginal()> _
        Public AddressLine1 As String

        <RoundtripOriginal()> _
        Public AddressLine2 As String

        <Required()> _
        <StringLength(30)> _
        <RoundtripOriginal()> _
        Public City As String

        <RoundtripOriginal()> _
        Public CountryRegion As String
        
        Public CustomerAddresses As EntityCollection(Of CustomerAddress)

        <RoundtripOriginal()> _
        Public ModifiedDate As DateTime

        <Required()> _
        <RoundtripOriginal()> _
        Public PostalCode As String

        <Exclude()> _
        Public rowguid As Guid

        <RoundtripOriginal()> _
        Public StateProvince As String
    End Class
End Class
[MetadataTypeAttribute(typeof(Address.AddressMetadata))]
public partial class Address
{

    internal sealed class AddressMetadata
    {
        // Metadata classes are not meant to be instantiated.
        private AddressMetadata()
        {
        }

        public int AddressID { get; set; }

        [Required]
        [StringLength(60)]
        [RoundtripOriginal]
        public string AddressLine1 { get; set; }

        [RoundtripOriginal]
        public string AddressLine2 { get; set; }

        [Required]
        [StringLength(30)]
        [RoundtripOriginal]
        public string City { get; set; }

        [RoundtripOriginal]
        public string CountryRegion { get; set; }

        public EntityCollection<CustomerAddress> CustomerAddresses { get; set; }

        [RoundtripOriginal]
        public DateTime ModifiedDate { get; set; }

        [Required]
        [RoundtripOriginal]
        public string PostalCode { get; set; }

        [Exclude]
        public Guid rowguid { get; set; }

        [RoundtripOriginal]
        public string StateProvince { get; set; }
    }
}

Vous pouvez créer un attribut de validation personnalisé en ajoutant un fichier de code partagé et en créant dans ce fichier une classe qui implémente la logique de validation. Lorsque vous définissez la classe de validation personnalisée, vous devez fournir au moins un code différent des propriétés implémentées automatiquement afin que la classe soit correctement générée dans le projet client. Pour obtenir un exemple, consultez Procédure : Valider des données.

La classe Entity implémente l'interface INotifyDataErrorInfo. Cette interface définit les membres qui fournissent une prise en charge de la validation synchrone et asynchrone. Avec l'interface INotifyDataErrorInfo, les erreurs de validation sont communiquées au projet client sans lever d'exception. Pour plus d'informations sur INotifyDataErrorInfo, consultez Interface INotifyDataErrorInfo.

Vous retournez le résultat d'un contrôle de validation en créant une instance de la classe ValidationResult.

L'exemple suivant montre une classe de validation personnalisée qui retourne les résultats via une instance de la classe ValidationResult.

Imports System
Imports System.ComponentModel.DataAnnotations

Public Module GenderValidator
    Public Function IsGenderValid(ByVal gender As String, ByVal context As ValidationContext) As ValidationResult
        If gender = "M" OrElse gender = "m" OrElse gender = "F" OrElse gender = "f" Then
            Return ValidationResult.Success
        Else
            Return New ValidationResult("The Gender field only has two valid values 'M'/'F'", New String() {"Gender"})
        End If
    End Function
End Module
using System;
using System.ComponentModel.DataAnnotations;

namespace HRApp.Web
{
    public static class GenderValidator
    {
        public static ValidationResult IsGenderValid(string gender, ValidationContext context)
        {
            if (gender == "M" || gender == "m" || gender == "F" || gender == "f")
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" });
            }
        }
    }
}

Accès concurrentiel aux données

Les Services RIA WCF prennent en charge l'accès concurrentiel optimiste afin de garantir la cohérence des données et comptent sur les développeurs pour fournir la logique de gestion des conflits potentiels pouvant survenir lors de la mise à jour d'une source de données. Si vous permettez aux utilisateurs de mettre à jour ou de supprimer des données, assurez-vous que les données dans la source de données n'ont pas été modifiées par un autre processus.

Par défaut, les Services RIA ne transmettent pas l'intégralité de l'entité d'origine, avec les valeurs modifiées, à la couche d'accès aux données où vérifier l'accès concurrentiel aux données. Au lieu de cela, les Services RIA stockent et retransmettent uniquement les membres marqués avec l'attribut RoundtripOriginalAttribute. Cette implémentation permet d'optimiser les performances de votre application en spécifiant uniquement les membres qui doivent participer au contrôle d'accès concurrentiel.

Ce comportement est implémenté par l'application de l'attribut aux propriétés dans une classe de métadonnées ou à la classe ou aux classes de métadonnées elles-mêmes, lors de l'utilisation d'Entity Framework. Les attributs peuvent également être appliqués directement aux propriétés ou aux classes de types CLR lors de l'utilisation de modèles de données définies POCO. Pour plus d'informations, consultez Procédure : Ajouter des classes de métadonnées.

Transactions

L'infrastructure des Services RIA ne crée pas automatiquement de transactions, mais vous pouvez ajouter des transactions explicites lors de la soumission de modifications. Pour créer votre propre transaction explicite, vous devez substituer la méthode Submit. Pour plus d'informations, consultez Procédure : Ajouter des transactions explicites à un service de domaine.

Voir aussi

Concepts

Sécurité des Services RIA WCF