Modèles de présentation

Les Services RIA WCF vous permettent de créer des modèles de données qui regroupent les données de plusieurs entités dans la couche d'accès aux données, appelés modèles de présentation. Vous utilisez cette fonctionnalité lorsque vous ne voulez pas exposer directement au client les entités de votre couche d'accès aux données. Lorsque vous utilisez un modèle de présentation, vous pouvez répondre aux modifications apportées dans la couche d'accès aux données en modifiant uniquement le modèle de présentation et non le client. Vous pouvez également simplifier le code client en concevant un modèle qui regroupe uniquement les champs qui concernent les utilisateurs du client. Cette rubrique décrit comment créer, interroger et mettre à jour un modèle de présentation et comment retransmettre des valeurs au client lorsque des modifications ont été définies dans la couche intermédiaire ou dans la source de données.

Création du modèle de présentation

La structure de la base de données exigée pour maintenir l'intégrité des données peut être plus compliquée que nécessaire pour les entités de votre application cliente. Vous pouvez créer un modèle de présentation qui simplifie cette structure de données en combinant les champs qui concernent votre application en un modèle de présentation. Par exemple, dans l'exemple de base de données AdventureWorksLT, vous récupérez les données client et adresses via les tables Customer, CustomerAddress et Address .

RS_CustomerEntities

Vous créez un modèle de présentation en créant une classe dans le projet serveur et en définissant les propriétés vous voulez rendre disponibles. Les propriétés que vous définissez correspondent aux propriétés que vous voulez exposer à partir des entités. Par exemple, vous pouvez créer la classe CustomerPresentationModel suivante dans le projet serveur pour présenter seulement le champ que vous voulez dans les tables Customer, CustomerAddress et Address.

Public Class CustomerPresentationModel
    <Key()> _
    Public Property CustomerID As Integer
    Public Property FirstName As String
    Public Property LastName As String
    Public Property EmailAddress As String
    Public Property Phone As String
    Public Property AddressType As String
    Public Property AddressLine1 As String
    Public Property AddressLine2 As String
    Public Property City As String
    Public Property StateProvince As String
    Public Property PostalCode As String
    Public Property AddressID As Integer
    Public Property AddressModifiedDate As DateTime
    Public Property CustomerModifiedDate As DateTime
End Class
public class CustomerPresentationModel
{
    [Key]
    public int CustomerID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public string Phone { get; set; }
    public string AddressType { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string StateProvince { get; set; }
    public string PostalCode { get; set; }
    public int AddressID { get; set; }
    public DateTime AddressModifiedDate { get; set; }
    public DateTime CustomerModifiedDate { get; set; }
}

Interrogation et modification de valeurs dans le modèle de présentation

Après avoir créé le modèle de présentation, vous l'exposez au projet client en ajoutant un service de domaine qui interagit avec le type de présentation. Les valeurs d'entité sont exposées uniquement via ce service de domaine et ne sont pas exposées via un service de domaine qui expose l'entité entière. L'exemple suivant illustre un service de domaine qui dérive de la classe DomainService.

[EnableClientAccess()]
public class CustomerDomainService : DomainService
{
    AdventureWorksLT_DataEntities context = new AdventureWorksLT_DataEntities();
}

Pour récupérer des données, vous ajoutez une méthode de requête au service de domaine. Dans la méthode de requête, vous récupérez les données pertinentes des entités dans la couche d'accès aux données et définissez ces valeurs avec les propriétés correspondantes dans une nouvelle instance du modèle de présentation. Depuis la méthode de requête, vous retournez soit une instance du type du modèle de présentation, soit un IQueryable’1 où le type générique est votre type CustomerPresentationModel. L'exemple suivant montre une méthode de requête pour le modèle de présentation client.

Public Function GetCustomersWithMainOffice() As IQueryable(Of CustomerPresentationModel)
    Return From c In context.Customers
        Join ca In context.CustomerAddresses On c.CustomerID Equals ca.CustomerID
        Join a In context.Addresses On ca.AddressID Equals a.AddressID
        Where ca.AddressType = "Main Office"
               Select New CustomerPresentationModel() With _
               {
                   .CustomerID = c.CustomerID,
                   .FirstName = c.FirstName,
                   .LastName = c.LastName,
                   .EmailAddress = c.EmailAddress,
                   .Phone = c.Phone,
                   .AddressType = ca.AddressType,
                   .AddressLine1 = a.AddressLine1,
                   .AddressLine2 = a.AddressLine2,
                   .City = a.City,
                   .StateProvince = a.StateProvince,
                   .PostalCode = a.PostalCode,
                   .AddressID = a.AddressID,
                   .AddressModifiedDate = a.ModifiedDate,
                   .CustomerModifiedDate = c.ModifiedDate
               }
End Function
public IQueryable<CustomerPresentationModel> GetCustomersWithMainOffice()
{
    return from c in context.Customers
        join ca in context.CustomerAddresses on c.CustomerID equals ca.CustomerID
        join a in context.Addresses on ca.AddressID equals a.AddressID
        where ca.AddressType == "Main Office"
           select new CustomerPresentationModel()
           {
               CustomerID = c.CustomerID,
               FirstName = c.FirstName,
               LastName = c.LastName,
               EmailAddress = c.EmailAddress,
               Phone = c.Phone,
               AddressType = ca.AddressType, 
               AddressLine1 = a.AddressLine1, 
               AddressLine2 = a.AddressLine2,
               City = a.City, 
               StateProvince = a.StateProvince, 
               PostalCode = a.PostalCode,
               AddressID = a.AddressID,
               AddressModifiedDate = a.ModifiedDate,
               CustomerModifiedDate = c.ModifiedDate
           };
}

Étant donné que les entités (Customer, CustomerAddress et Address) dans la couche d'accès aux données ne sont pas exposées par le service de domaine, ces types ne sont pas générés dans le projet client. Au lieu de cela, seul le type CustomerPresentationModel est généré dans le projet client.

Pour mettre à jour des données via le modèle de présentation, vous créez une méthode de mise à jour et vous définissez la logique pour enregistrer les valeurs à partir du modèle de présentation sur les entités. Vous trouverez un exemple de méthode de mise à jour à la fin de la section suivante.

Retransmettre les valeurs au client

Après avoir soumis les modifications, vous pouvez retransmettre au client des valeurs qui sont définies dans la logique de couche intermédiaire ou dans la source de données. Les Services RIA fournissent la méthode Associate pour mapper les valeurs de l'entité et les retransmettre au modèle de présentation. Dans cette méthode, vous fournissez une méthode de rappel appelée une fois les modifications soumises. Dans la méthode de rappel, vous affectez au modèle de présentation toutes les valeurs qui ont été modifiées dans la couche intermédiaire. Vous effectuez cette opération pour être sûr que le client possède les valeurs actuelles.

L'exemple suivant indique comment mettre à jour des valeurs dans les entités et comment mapper des données modifiées pour les retransmettre au modèle de présentation.

<Update()> _
Public Sub UpdateCustomer(ByVal customerPM As CustomerPresentationModel)
    Dim customerEntity As Customer = context.Customers.Where(Function(c) c.CustomerID = customerPM.CustomerID).FirstOrDefault()
    Dim customerAddressEntity As CustomerAddress = context.CustomerAddresses.Where(Function(ca) ca.CustomerID = customerPM.CustomerID And ca.AddressID = customerPM.AddressID).FirstOrDefault()
    Dim addressEntity As Address = context.Addresses.Where(Function(a) a.AddressID = customerPM.AddressID).FirstOrDefault()

    customerEntity.FirstName = customerPM.FirstName
    customerEntity.LastName = customerPM.LastName
    customerEntity.EmailAddress = customerPM.EmailAddress
    customerEntity.Phone = customerPM.Phone
    customerAddressEntity.AddressType = customerPM.AddressType
    addressEntity.AddressLine1 = customerPM.AddressLine1
    addressEntity.AddressLine2 = customerPM.AddressLine2
    addressEntity.City = customerPM.City
    addressEntity.StateProvince = customerPM.StateProvince
    addressEntity.PostalCode = customerPM.PostalCode

    Dim originalValues As CustomerPresentationModel = Me.ChangeSet.GetOriginal(customerPM)

    If (originalValues.FirstName <> customerPM.FirstName Or
            originalValues.LastName <> customerPM.LastName Or
            originalValues.EmailAddress <> customerPM.EmailAddress Or
            originalValues.Phone <> customerPM.Phone) Then
        customerEntity.ModifiedDate = DateTime.Now
    End If

    If (originalValues.AddressLine1 <> customerPM.AddressLine1 Or
            originalValues.AddressLine2 <> customerPM.AddressLine2 Or
            originalValues.City <> customerPM.City Or
            originalValues.StateProvince <> customerPM.StateProvince Or
            originalValues.PostalCode <> customerPM.PostalCode) Then
        addressEntity.ModifiedDate = DateTime.Now
    End If

    context.SaveChanges()

    Me.ChangeSet.Associate(customerPM, customerEntity, AddressOf MapCustomerToCustomerPM)
    Me.ChangeSet.Associate(customerPM, addressEntity, AddressOf MapAddressToCustomerPM)
End Sub

Private Sub MapCustomerToCustomerPM(ByVal customerPM As CustomerPresentationModel, ByVal customerEntity As Customer)
    customerPM.CustomerModifiedDate = customerEntity.ModifiedDate
End Sub

Private Sub MapAddressToCustomerPM(ByVal customerPM As CustomerPresentationModel, ByVal addressEntity As Address)
    customerPM.AddressModifiedDate = addressEntity.ModifiedDate
End Sub
[Update]
public void UpdateCustomer(CustomerPresentationModel customerPM)
{
    Customer customerEntity = context.Customers.Where(c => c.CustomerID == customerPM.CustomerID).FirstOrDefault();
    CustomerAddress customerAddressEntity = context.CustomerAddresses.Where(ca => ca.CustomerID == customerPM.CustomerID && ca.AddressID == customerPM.AddressID).FirstOrDefault();
    Address addressEntity = context.Addresses.Where(a => a.AddressID == customerPM.AddressID).FirstOrDefault();

    customerEntity.FirstName = customerPM.FirstName;
    customerEntity.LastName = customerPM.LastName;
    customerEntity.EmailAddress = customerPM.EmailAddress;
    customerEntity.Phone = customerPM.Phone;
    customerAddressEntity.AddressType = customerPM.AddressType;
    addressEntity.AddressLine1 = customerPM.AddressLine1;
    addressEntity.AddressLine2 = customerPM.AddressLine2;
    addressEntity.City = customerPM.City;
    addressEntity.StateProvince = customerPM.StateProvince;
    addressEntity.PostalCode = customerPM.PostalCode;

    CustomerPresentationModel originalValues = this.ChangeSet.GetOriginal(customerPM);

    if (originalValues.FirstName != customerPM.FirstName ||
        originalValues.LastName != customerPM.LastName ||
        originalValues.EmailAddress != customerPM.EmailAddress ||
        originalValues.Phone != customerPM.Phone)
    {
        customerEntity.ModifiedDate = DateTime.Now;
    }

    if (originalValues.AddressLine1 != customerPM.AddressLine1 ||
        originalValues.AddressLine2 != customerPM.AddressLine2 ||
        originalValues.City != customerPM.City ||
        originalValues.StateProvince != customerPM.StateProvince ||
        originalValues.PostalCode != customerPM.PostalCode)
    {
        addressEntity.ModifiedDate = DateTime.Now;
    }

    context.SaveChanges();

    this.ChangeSet.Associate(customerPM, customerEntity, MapCustomerToCustomerPM);
    this.ChangeSet.Associate(customerPM, addressEntity, MapAddressToCustomerPM);
}

private void MapCustomerToCustomerPM(CustomerPresentationModel customerPM, Customer customerEntity)
{
    customerPM.CustomerModifiedDate = customerEntity.ModifiedDate;
}

private void MapAddressToCustomerPM(CustomerPresentationModel customerPM, Address addressEntity)
{
    customerPM.AddressModifiedDate = addressEntity.ModifiedDate;
}