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
.
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;
}