Darstellungsmodelle

WCF RIA Services ermöglicht Ihnen das Erstellen von Datenmodellen, in denen Daten aus mehreren Entitäten in der Datenzugriffsebene aggregiert werden. Ein solches Modell wird als Darstellungsmodell bezeichnet. Diese Funktion wird verwendet, wenn die Entitäten in der Datenzugriffsebene nicht direkt für den Client verfügbar gemacht werden sollen. Wenn Sie ein Darstellungsmodell verwenden, können Sie auf Änderungen in der Datenzugriffsebene reagieren, indem Sie nur das Darstellungsmodell und nicht den Client ändern. Zudem können Sie den Clientcode vereinfachen, indem Sie ein Modell entwerfen, in dem nur die für Benutzer des Clients relevanten Felder aggregiert sind. In diesem Thema wird beschrieben, wie ein Darstellungsmodell erstellt, abgefragt und aktualisiert wird und Werte an den Client zurückgegeben werden, wenn Änderungen in der mittleren Ebene oder der Datenquelle vorgenommen wurden.

Erstellen des Darstellungsmodells

Die erforderliche Datenbankstruktur zum Aufrechterhalten der Datenintegrität ist möglicherweise komplizierter als die Struktur, die Sie für die Entitäten in der Clientanwendung benötigen. Sie können ein Darstellungsmodell erstellen, das diese Datenstruktur vereinfacht, indem Sie die für die Anwendung relevanten Felder in einem Darstellungsmodell kombinieren. In der AdventureWorksLT-Beispieldatenbank werden Kunden- und Adressdaten z. B. mithilfe der Tabellen Customer, CustomerAddress und Address abgerufen.

RS_CustomerEntities

Sie erstellen ein Darstellungsmodell, indem Sie eine Klasse im Serverprojekt erstellen und die Eigenschaften definieren, die Sie verfügbar machen möchten. Die definierten Eigenschaften entsprechen den Eigenschaften, die Sie von den Entitäten verfügbar machen möchten. Sie können z. B. die folgende CustomerPresentationModel-Klasse im Serverprojekt erstellen, um nur das gewünschte Feld aus den Tabellen Customer, CustomerAddress und Address darzustellen.

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

Abfragen und Ändern von Werten im Darstellungsmodell

Nachdem Sie das Darstellungsmodell erstellt haben, machen Sie es für das Clientprojekt verfügbar, indem Sie einen Domänendienst hinzufügen, der mit dem Darstellungstyp interagiert. Die Entitätswerte werden nur durch diesen Domänendienst verfügbar gemacht und nicht durch einen Domänendienst, der die gesamte Entität verfügbar macht. Das folgende Beispiel zeigt einen von der DomainService-Klasse abgeleiteten Domänendienst.

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

Um Daten abzurufen, fügen Sie dem Domänendienst eine Abfragemethode hinzu. In der Abfragemethode rufen Sie die relevanten Daten aus den Entitäten in der Datenzugriffsebene ab, und Sie legen diese Werte in einer neuen Instanz des Darstellungsmodells auf die entsprechenden Eigenschaften fest. Von der Abfragemethode geben Sie entweder eine Instanz des Darstellungsmodelltyps oder IQueryable’1 zurück, wobei es sich beim generischen Typ um den CustomerPresentationModel-Typ handelt. Das folgende Beispiel zeigt eine Abfragemethode für das Kundendarstellungsmodell.

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

Da die Entitäten in der Datenzugriffsebene (Customer, CustomerAddress und Address) nicht vom Domänendienst verfügbar gemacht werden, werden diese Typen nicht im Clientprojekt generiert. Stattdessen wird nur der CustomerPresentationModel-Typ im Clientprojekt generiert.

Um Daten anhand des Darstellungsmodells zu aktualisieren, müssen Sie eine Updatemethode erstellen und die Logik zum Speichern der Werte aus dem Darstellungsmodell in den Entitäten definieren. Ein Beispiel für eine Updatemethode finden Sie am Ende des nächsten Abschnitts.

Zurückgeben von Werten an den Client

Nach dem Übermitteln von Änderungen möchten Sie möglicherweise Werte an den Client zurückgeben, die in der Logik der mittleren Ebene oder der Datenquelle festgelegt sind. RIA Services stellt die Associate-Methode bereit, um das erneute Zuordnen von Werten aus der Entität zum Darstellungsmodell zu ermöglichen. In dieser Methode geben Sie eine Rückrufmethode an, die nach dem Übermitteln der Änderungen aufgerufen wird. In der Rückrufmethode weisen Sie alle Werte, die in der mittleren Ebene geändert wurden, dem Darstellungsmodell zu. Durch diesen Schritt stellen Sie sicher, dass der Client über die aktuellen Werte verfügt.

Das folgende Beispiel zeigt, wie Werte in den Entitäten aktualisiert und geänderte Daten wieder dem Darstellungsmodell zugeordnet werden.

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