Gewusst wie: Erstellen eines Domänendiensts für als POCO definierte Entitäten

In diesem Thema wird veranschaulicht, wie mit WCF RIA Services ein Domänendienst erstellt wird, der einfache alte CLR-Objekte (POCO) verwendet. Es wird gezeigt, wie eine einfache RIA Services -Anwendung auf POCO-Basis erstellt wird, an deren Beispiel insbesondere die Auswirkungen einer Verwendung der RIA Services -Tools (Assistenten und Dialogfelder) in den verschiedenen Schritten des Verfahrens verdeutlicht werden kann. Mit den von POCO gestellten Daten kann eine Anwendung von der Abhängigkeit von Back-End-Datenbanken befreit werden, und die Portabilität kann erhöht, die Datensicherheit verbessert oder Tests können erleichtert werden. Der automatisch generierte Clientcode wird analog zu Linq to SQL oder Entity Framework vollständig von RIA Services mit POCO-Entitäten unterstützt. Tatsächlich verhält sich der RIA Services -Domänendienst im Hinblick auf die Datenquelle agnostisch, sodass die POCO-Klasse später durch eine Komponente ersetzt werden kann, die auf Daten aus einer anderen Quelle zugreift, beispielsweise eine Datenbank, ohne den Domänendienst selbst zu ändern.

Für das an dieser Stelle beschriebene Verfahren müssen neben WCF RIA Services mehrere Programme installiert und ordnungsgemäß konfiguriert werden, darunter Visual Studio 2010, Silverlight Developer-Laufzeit und -SDK. Das WCF RIA Services-Toolkit ist jedoch nicht erforderlich. Ausführliche Anweisungen für jede dieser erforderlichen Komponenten finden Sie in den Themen unter Erforderliche Komponenten für WCF RIA Services. Folgen Sie den Anweisungen für diese erforderlichen Programme, bevor Sie mit diesem Gewusst-wie-Thema fortfahren, um sicherzustellen, dass so wenig Probleme wie möglich auftreten.

Erstellen einer RIA Services-Projektmappe

  1. Erstellen Sie in Visual Studio 2010 ein neues RIA Services -Projekt, indem Sie Datei, Neu und dann Projekt auswählen.

    Das Dialogfeld Neues Projekt wird angezeigt.

  2. Wählen Sie in der Gruppe Silverlight unter Installierte Vorlagen die Vorlage Silverlight-Anwendung aus, und geben Sie für das neue Projekt den Namen RIAServicesPocoExample ein.

  3. Klicken Sie auf OK.

    Das Dialogfeld Neue Silverlight-Anwendung wird angezeigt.

  4. Aktivieren Sie das Kontrollkästchen WCF RIA Services aktivieren im unteren Bereich des Dialogfelds. Durch Aktivieren dieses Kontrollkästchens wird ein RIA Services -Link zwischen dem Client- und dem Serverprojekt erstellt. Um diese Verbindung zu aktivieren, werden dem Clientprojekt von diesem Tool folgende Verweise hinzugefügt:

    • System.ComponentModel.DataAnnotations

    • System.Runtime.Serialization

    • System.ServiceModel.dll

    • System.ServiceModel.DomainServices.Client

    • System.ServiceModel.DomainServices.Client.Web

    • System.ServiceModel.Web.Extensions

    • System.Windows.Browser

  5. Klicken Sie auf OK, um die Projektmappe zu erstellen.

    Die Projektmappe enthält zwei Projekte: ein Client- und ein Serverprojekt.

    • RIAServicesPocoExample: Das Clientprojekt mit dem Silverlight-Code, den Sie zum Erstellen der Präsentationsebene verwendet haben.

    • RIAServicesPocoExample.Web: Das Serverprojekt mit dem Code der mittleren Ebene.

Erstellen eines Domänendiensts

  1. Klicken Sie mit der rechten Maustaste auf das Serverprojekt, und wählen Sie Hinzufügen und Neues Element aus.

  2. Wählen Sie in der Liste der Kategorien Web aus, und wählen Sie dann die Vorlage Domänendienstklasse aus.

  3. Nennen Sie die Klasse SovereignDomainService.cs (oder SovereignDomainService.vb).

  4. Klicken Sie auf Hinzufügen.

    Das Dialogfeld Neue Domänendienstklasse hinzufügen wird angezeigt.

  5. Stellen Sie sicher, dass das Kontrollkästchen Clientzugriff aktivieren aktiviert ist.

  6. Beachten Sie, dass im Dropdownmenü für Verfügbare DataContext-/ObjectContext-Klassen nur die Entität <leere Domänendienstklasse> ausgewählt werden und das Kontrollkästchen Zugeordnete Klassen für Metadaten generieren nicht aktiviert werden kann, da keine Datenkontexte mit diesem Dienst verknüpft werden können.

  7. Klicken Sie auf OK.

    Der Assistent führt mehrere Aufgaben aus. Er generiert eine leere SovereignDomainService-Klasse in einer neuen SovereignDomainService.cs-Datei (oder SovereignDomainService.vb-Datei) mit zugeordneten Attributen und using-Anweisungen. Außerdem werden dem Dienstprojekt vier Assemblyverweise und Konfigurationselemente der Web.config-Datei hinzugefügt.

  8. Sie können dies nachvollziehen, indem Sie die Datei SovereignDomainService.cs (oder SovereignDomainService.vb) öffnen, wenn sie nicht bereits automatisch geöffnet wurde. Die Datei weist die folgenden Eigenschaften auf:

    1. using-Anweisungen wurden hinzugefügt:

      • using System;

      • using System.Collections.Generic;

      • using System.ComponentModel;

      • using System.ComponentModel.DataAnnotations;

      • using System.Linq;

      • using System.ServiceModel.DomainServices.Hosting;

      • using System.ServiceModel.DomainServices.Server

    2. Die SovereignDomainService-Klasse leitet sich von der DomainService-Klasse ab, bei der es sich um eine abstrakte Basisklasse im RIA Services -Framework handelt. Dies ist die Basisklasse für alle Domänendienste, die in RIA Services verfügbar sind.

    3. Die SovereignDomainService-Klasse wird mit dem EnableClientAccessAttribute-Attribut markiert, um anzugeben, dass es für die Clientebene sichtbar ist.

  9. Die folgenden Verweise wurden dem Dienstprojekt vom Assistenten hinzugefügt:

    • System.ComponentModel.DataAnnotations

    • System.Runtime.Serialization

    • System.ServiceModel.DomainServices.Hosting

    • System.ServiceModel.DomainServices.Server

  10. Öffnen Sie nun die Web.config-Datei, und betrachten Sie die neuen Elemente, die vom Assistenten hinzugefügt wurden.

    <configuration>
        <system.webServer>
            <modules runAllManagedModulesForAllRequests="true">
                <add name="DomainServiceModule" preCondition="managedHandler"
                    type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </modules>
            <validation validateIntegratedModeConfiguration="false" />
        </system.webServer>
        <system.web>
            <httpModules>
                <add name="DomainServiceModule" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </httpModules>
            <compilation debug="true" targetFramework="4.0" />
        </system.web>
    
        <system.serviceModel>
            <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
                multipleSiteBindingsEnabled="true" />
        </system.serviceModel>
    </configuration>
    

    Mit Ausnahme des Konfigurationselements für .NET Framework 4 wurden diese Elemente über das Dialogfeld Neue Domänendienstklasse hinzufügen hinzugefügt. Mithilfe der Elemente werden verschiedene Optionen für das IIS-Hosting und ASP.NET zur Verfügung gestellt.

    1. Vom Assistenten wird ein <modules>-Element im <system.webserver>-Abschnitt hinzugefügt, das für das Hosting IIS 7 erforderlich ist.

    2. Vom Assistenten wird ein <add>-Element des <httpModules>-Elements im system.web-Abschnitt hinzugefügt, das für das Hosting von IIS 6 erforderlich ist.

    3. Bei den RIA Services -Domänendiensten handelt es sich um Windows Communication Foundation (WCF)-Dienste, die beim Hosten mit ASP.NET im ASP.NET-Kompatibilitätsmodus gehostet werden müssen. Diese Anforderung kann nicht im Code festgelegt werden, sondern muss in der Datei Web.config definiert sein. Der ASP.NET-Kompatibilitätsmodus wird aktiviert, indem die aspNetCompatibilityEnabled-Eigenschaft im <ServiceHostingEnvironment>-Element des Abschnitts <system.serviceModel> auf true festgelegt wird:

Hinzufügen der POCO-Klasse

  1. In diesem Verfahren wird beschrieben, wie für das RIA Services Framework angegeben wird, dass eine POCO-Klasse als Entitätstyp verwendet werden soll. Entitätstypen stellen Datenstrukturen für das Datenmodell der Anwendung bereit, und jeder Entitätstyp muss über einen eindeutigen Identitätsschlüssel verfügen. Die Struktur der Daten wird durch die darin enthaltenen Eigenschaften bestimmt. Der Entitätsschlüssel wird durch Abordnen einer Eigenschaft (oder einer Reihe von Eigenschaften) bereitgestellt, die einen eindeutigen Namen für jedes Entitätsobjekt bereitstellen müssen, um eine Unterscheidung von anderen Entitäten des gleichen Typs zu ermöglichen. Dies geschieht i. d. R. durch die Verwendung unterschiedlicher Metadaten. Dazu wird in diesem Verfahren das [Key]-Attribut auf eine Eigenschaft angewendet, und tatsächlich wird durch die Anwendung dieses Attributs dem RIA Services Framework mitgeteilt, dass es sich bei Instanzen der POCO-Klasse um Entitätsobjekte handelt.

  2. Öffnen Sie die Datei SovereignDomainSevice.cs.

  3. Fügen Sie im Bereich des RIAServicesPocoExample.Web-Namespaces unterhalb der als Stub-Out bereitgestellten SovereignDomainService-Klasse den folgenden Code für die Sovereign-Klasse hinzu:

    
    public class Sovereign
        {
            [Key]
            public int UniqueId { get; set; }
            public string Name { get; set; }
            public string House { get; set; }
            public string Dominion { get; set; }
            public int ReignStart { get; set; }
            public int ReignEnd { get; set; }
            public string Sobriquet { get; set; }
        }
    
  4. In diesem Beispiel stellt die UniqueId-Eigenschaft den Entitätsschlüssel dar, der einen eindeutigen Namen für die einzelnen Entitätsobjekte vom Typ Sovereign bereitstellt. Das [Key]-Attribut wird in der System.ComponentModel.DataAnnotations-Assembly definiert, die, ebenso wie die using-Anweisung für den entsprechenden Namespace, in dem es enthalten ist, bereits dem Serverprojekt hinzugefügt wurde. Der Entitätsschlüssel kann auch in einer Metadatendatei oder auf andere Weise angegeben werden; dies ist jedoch eine bequeme Möglichkeit der direkten Angabe in der POCO-Klasse.

  5. Fügen Sie die FetchSovereigns()-Methode der Sovereign-Klasse hinzu, die eine Liste von Sovereign-Instanzen zurückgibt:

    
    public List<Sovereign> FetchSovereigns()
            {
                List<Sovereign> sovereignList = new List<Sovereign>
                {
                new Sovereign()
                    {UniqueId = 1, 
                     Name = "John", 
                     House = "Plantagenet", 
                     Dominion = "Angevin Empire", 
                     ReignStart = 1167, 
                     ReignEnd = 1216, 
                     Sobriquet = "Lackland"
                    },
                new Sovereign()
                    {UniqueId = 2, 
                     Name = "Charles", 
                     House = "Stuart", 
                     Dominion = "England, Scotland, & Ireland", 
                     ReignStart = 1625, 
                     ReignEnd = 1649, 
                     Sobriquet = "The Martyr"
                    },
                new Sovereign()
                    {UniqueId = 3, 
                     Name = "William", 
                     House = "Dunkeld", 
                     Dominion = "Scotland", 
                     ReignStart = 1165, 
                     ReignEnd = 1249, 
                     Sobriquet = "The Lion"
                    },   
                new Sovereign()
                    {UniqueId = 4, 
                     Name = "Elizabeth", 
                     House = "Tudor", 
                     Dominion = "England", 
                     ReignStart = 1555, 
                     ReignEnd = 1609, 
                     Sobriquet = "The Virgin Queen"
                    },
                new Sovereign()
                    {UniqueId = 5, 
                     Name = "Ivan", 
                     House = "Vasilyevich", 
                     Dominion = "Russia", 
                     ReignStart = 1533, 
                     ReignEnd = 1584, 
                     Sobriquet = "The Terrible"
                    },
                new Sovereign()
                    {UniqueId = 6, 
                     Name = "Charles", 
                     House = "Valois", 
                     Dominion = "France", 
                     ReignStart = 1380, 
                     ReignEnd = 1422, 
                     Sobriquet = "The Mad"
                    }
                };
            return sovereignList;
            }
    

Definieren des Domänendiensts

  1. In diesem Verfahren wird beschrieben, wie eine Abfrage im Domänendienst erstellt wird, auf die vom Client zugegriffen werden kann, um Daten aus den POCO-Entitäten abzurufen. Das RIA Services Framework benötigt Informationen darüber, welche Methoden im Client in Form von Abfragen verfügbar gemacht werden sollen. Dies kann mithilfe einer Benennungskonvention erreicht werden. Methodennamen, die mit Get beginnen und einen IEnumerable<EntityType> oder einen IQueryable<EntityType> zurückgeben, werden vom RIA Services Framework als Abfragen erkannt.

    TipTipp:
    IQueryable leitet sich von IEnumerable her. Verwenden Sie IEnumerable für Auflistungen im Arbeitsspeicher, z. B. für die POCO-Entitäten, und verwenden Sie IQueryable für den Zugriff auf eine zugrunde liegende Datenquelle oder eine Remotedatenquelle, beispielsweise eine SQL-Datenbank.
  2. Fügen Sie der SovereignDomainService-Klasse die GetSovereign()-Methode hinzu.

    
            public IEnumerable<Sovereign> GetSovereigns()
            { 
                Sovereign sovereign = new Sovereign();
                return sovereign.FetchSovereigns();
            }
    
  3. Dadurch werden alle souveränen Entitäten aus der Auflistung zurückgegeben. Gewöhnlich wird jedoch nur eine Teilmenge der Entitäten benötigt. Zur Veranschaulichung können Sie diese Abfrage so bearbeiten, dass nur die Souveräne aus der Liste zurückgegeben werden, die im Mittelalter regiert haben, d. h. wo sovereign.ReignEnd <= 1500 ist. Dies wird mit dem folgenden Code erreicht:

            public IEnumerable<Sovereign> GetSovereignsByReignEnd(int ReignedBefore)
            {
                Sovereign sovereign = new Sovereign();
                return sovereign.FetchSovereigns().Where<Sovereign>(p => p.ReignEnd <= 1500);
            }
    
  4. Erstellen Sie (STRG+UMSCHALT+B) die Projektmappe, um den automatisch generierten Clientproxycode zu erstellen.

  5. Wählen Sie im Projektmappen-Explorer das Clientprojekt RIAServicesPocoExample aus, und klicken Sie oben im Fenster auf das Symbol Alle Dateien anzeigen. Überprüfen Sie die Datei RIAServicesPocoExample.Web.g.cs im Ordner Generated_Code. Überprüfen Sie den automatisch generierten Code in dieser Datei, und achten Sie auf folgende Elemente:

    • Eine WebContext-Klasse, die von der WebContextBase-Klasse abgeleitet wird, wird generiert und zum Verwalten des Anwendungskontexts verwendet.

    • Eine Sovereign-Klasse, die sich von der Entity-Klasse ableitet, wird für die vom Domänendienst verfügbar gemachte Entität generiert. Die Sovereign-Entitätsklasse im Clientprojekt entspricht der Sovereign-Entität auf dem Server.

    • Eine SovereignDomainContext-Klasse, die von der DomainContext-Klasse abgeleitet wird, wird generiert. Diese Klasse verfügt über die Methode GetSovereignsByReignEndQuery, die der im Domänendienst erstellten Abfragemethode entspricht.

  6. Weitere Informationen zur automatischen Codegenerierung finden Sie im Thema Clientcodegenerierung. Informationen zum Anpassen der Codegenerierung finden Sie im Thema Anpassen des generierten Codes.

Anzeigen des Abfrageergebnisses im Silverlight-Client

  1. Öffnen Sie die Datei MainPage.xaml.

  2. Ziehen Sie von der Toolbox auf der linken Seite ein DataGrid-Steuerelement in das Grid-Element in der XAML-Ansicht.

    Durch Ziehen des DataGrid-Steuerelements von der Toolbox wird eine using System.Windows.Controls-Namespaceanweisung der Datei MainPage.xaml.cs hinzugefügt, und Verweise auf die Assembly System.Windows.Controls.Data und die Assembly System.Windows.Controls.Data.Input werden dem Clientprojekt automatisch hinzugefügt.

    CautionVorsicht:
    Wenn Sie das DataGrid hinzufügen, ohne es von der Toolbox zu ziehen, müssen die Verweise auf die Assemblys dem Clientprojekt und die using-Anweisung in der CodeBehind-Datei manuell hinzugefügt werden.
  3. Ändern Sie den Wert von AutoGeneratedColums in True, benennen Sie das DataGrid-Element SovereignGrid, und passen Sie die Height und die Width an, wie im folgenden XAML veranschaulicht.

    
    <Grid x:Name="LayoutRoot" Background="White">
         <sdk:DataGrid AutoGenerateColumns="True" 
                       Height="200" 
                       HorizontalAlignment="Left" 
                       Margin="157,86,0,0" 
                       Name="SovereignGrid" 
                       VerticalAlignment="Top"
                       Width="600" />
    </Grid>
    
  4. Öffnen Sie die Datei MainPage.xaml.cs.

  5. Fügen Sie using (C#) oder Imports (Visual Basic) zwei Anweisungen hinzu: using RIAServicesPocoExample.Web; und using System.ServiceModel.DomainServices.Client;.

    Der RIAServicesPocoExample.Web-Namespace ist der Namespace, der den generierten Code für das Clientprojekt in der Datei RIAServicesPocoExample.Web.g.cs (oder RIAServicesPocoExample.Web.g.vb) enthält.

  6. Zur Instanziierung von SovereignDomainContext muss die Codezeile private SovereignDomainContext _sovereignContext = new SovereignDomainContext(); in der MainPage-Klasse hinzugefügt werden.

  7. Rufen Sie Kundenentitäten ab, indem Sie die GetSovereignsQuery-Methode mit LoadOperation aufrufen: LoadOperation<Sovereign> loadOp = this._sovereignContext.Load(this._sovereignContext.GetSovereignsByReignEndQuery(1500));.

  8. Binden Sie die in das DataGrid geladenen Entitäten mit SovereignGrid.ItemsSource = loadOp.Entities;.

    Zusammenfassung: Die Datei MainPage.xaml.cs sollte nun den folgenden Code enthalten:

    //Namespaces added
    using RIAServicesPocoExample.Web;
    using System.ServiceModel.DomainServices.Client;
    
    namespace RIAServicesPocoExample
    {
        public partial class MainPage : UserControl
    
        {
            private SovereignDomainContext _sovereignContext = new SovereignDomainContext();
    
            public MainPage()
            {
    
                InitializeComponent();
    
                  LoadOperation<Sovereign> loadOp = this._sovereignContext.Load(this._sovereignContext.GetSovereignsByReignEndQuery(1500));
                  SovereignGrid.ItemsSource = loadOp.Entities;
            }
        }
    }
    
  9. Führen Sie die Anwendung aus (F5).

    Die Tabelle sollte im Browser nur mit den Eigenschaften der mittelalterlichen Souveräne (in alphabetischer Reihenfolge) angezeigt werden (deren Herrschaft vor 1500 u. Z. endete).

Sicherheit

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Abrufen und Anzeigen von Daten aus einem Domänendienst

Konzepte

Clientcodegenerierung