Partager via


Procédure pas à pas : Partage d'entités entre plusieurs services de domaine

Vous devrez peut-être afficher des données provenant de diverses sources de données ou exposer une entité à plusieurs services de domaine dans votre application Services RIA WCF. Par exemple, un site Web d'e-commerce devra peut-être intégrer des données de son système de traitement des commandes avec les produits d'un service de domaine tiers. Les Services RIA autorisent ce scénario en prenant en charge les références entre entités de types DomainContext différents. Pour plus d'informations sur la nature et les limitations de cette fonctionnalité, consultez la rubrique Entités partagées.

Dans cette procédure pas à pas, vous verrez deux façons différentes de définir une association entre entités se trouvant dans des instances de contexte de domaine différentes :

  • Dans la première partie, l'association se définit en ajoutant le code au projet serveur.

  • Dans la deuxième partie, l'association est définie par le code dans le projet client.

Les deux approches de la définition de l'association utilisent le même code sur le client pour récupérer et afficher les données.

Pour mieux comprendre cette procédure pas à pas, vous allez créer deux modèles d'entité et deux services de domaine pour exposer les données dans l'exemple de base de données AdventureWorksLT. En principe, vous ne créeriez pas deux modèles d'entité et deux services de domaine pour exposer des données provenant d'une même source. Nous n'utilisons cette approche ici que pour simplifier l'exemple tout en vous enseignant une technique que vous pourrez utiliser dans des scénarios plus complexes employant plusieurs sources de données. Pour voir un autre exemple d'affichage de données liées à partir d'une source de données unique, consultez Procédure pas à pas : Affichage de données liées dans une application métier Silverlight.

Configuration requise

Cette procédure pas à pas, ainsi que les autres procédures du même type présentées dans la documentation des Services RIA nécessite au préalable l'installation et la configuration correctes de plusieurs programmes, tels que Visual Studio 2010 et le Developer Runtime et SDK Silverlight, en plus des Services RIA WCF et du kit de ressources des Services RIA WCF. Ces procédures nécessitent également l'installation et la configuration de SQL Server 2008 R2 Express with Advanced Services et l'installation de la base de données AdventureWorks OLTP et LT.

Vous trouverez des instructions détaillées pour satisfaire chacune de ces conditions préalables dans les rubriques du nœud Conditions préalables pour les Services RIA WCF. Suivez ces instructions avant de poursuivre, pour être sûr de rencontrer le moins de problèmes possibles en effectuant ces procédures pas à pas des Services RIA .

Création d'une solution, modèles de données et services de domaine

Pour installer une solution de Services RIA

  1. Dans Visual Studio 2010, créez un projet Services RIA en sélectionnant Fichier, Nouveau, puis Projet.

    La boîte de dialogue Nouveau projet s'affiche.

  2. Sélectionnez le modèle Application Silverlight dans les modèles Silverlight et nommez le nouveau projet SharedEntityExample.

  3. Cliquez sur OK.

    La boîte de dialogue Nouvelle application Silverlight s'ouvre.

  4. Activez la case à cocher Activer les services RIA WCF au bas de la fenêtre.

  5. Cliquez sur OK pour créer la solution.

Pour créer deux Entity Data Models

  1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet serveur, (SharedEntityExample.Web), sélectionnez Ajouter, puis Nouvel élément.

    La boîte de dialogue Ajouter un nouvel élément s'affiche.

  2. Sélectionnez Données dans la liste des Modèles installés, gauche, puis sélectionnez le modèle Entity Data Model ADO.NET.

  3. Nommez le nouveau fichier SalesModel.edmx, puis cliquez sur Ajouter.

    L'Assistant EDM s'affiche.

  4. Sur l'écran Choisir le contenu du modèle, sélectionnez Générer à partir de la base de données, puis cliquez sur Suivant.

  5. Sur l'écran Choisir votre connexion de données, créez une connexion de données à la base de données AdventureWorksLT.

  6. Si la base de données AdventureWorksLT ne s'affiche pas dans la liste déroulante, cliquez sur Nouvelle connexion, sélectionnez le Nom du serveur correct, puis sélectionnez la base de données AdventureWorksLT dans le menu déroulant de la zone Connexion à la base de données plus bas dans la fenêtre. Sélectionnez le bouton Tester la connexion pour vérifier que la base de données est accessible et cliquez sur OK.

  7. Vérifiez que la case à cocher Enregistrer les paramètres de connexion de l'entité dans Web.Config en tant que est activée lorsque vous êtes ramené à l'Assistant Entity Data Model et donnez aux paramètres de connexion de l'entité la valeur Sales_DataEntities.

  8. Cliquez sur Suivant.

  9. Sur l'écran Choisir vos objets de base de données, sélectionnez la table SalesOrderHeader.

  10. Cliquez sur Terminer.

    Le modèle d'entité est créé pour la table.

  11. Répétez les étapes précédentes de cette section pour créer un autre Entity Data Model pour la base de données AdventureWorksLT, mais nommez celui-ci CustomerModel.edmx, donnez au paramètre de connexion de l'entité la valeur Customer_DataEntities dans Web.config et sélectionnez le tableau Customer (SalesLT).

  12. Générez la solution.

  13. Ouvrez le fichier de code du modèle d'entité Ventes, et notez que la classe SalesOrderHeader possède une propriété CustomerID. Vous utiliserez cette propriété pour associer SalesOrderHeader et Customer.

Pour créer les services de domaine

  1. Cliquez avec le bouton droit sur le projet serveur SharedEntityExample.Web, sélectionnez Ajouter, puis Nouvel élément.

  2. Dans la liste des catégories, sélectionnez Web, puis sélectionnez le modèle Classe DomainService.

  3. Nommez la classe SalesDomainService.cs (ou SalesDomainService.vb).

  4. Cliquez sur Ajouter.

    La boîte de dialogue Ajouter une nouvelle classe de service de domaine s'ouvre.

  5. Assurez-vous que la case à cocher Activer l'accès client est activée.

  6. Dans la liste Classes DataContext/ObjectContext disponibles, sélectionnez l'objet de contexte de données Sales_DataEntities (Entity Framework).

    TipConseil :
    Si vous avez donné un autre nom à votre connexion de données lorsque vous avez créé le modèle d'entité, sélectionnez l'objet de contexte de données qui contient l'entité SalesOrderHeader.
  7. Sous Entités, activez la case à cocher de l'entité SalesOrderHeader.

  8. Cliquez sur OK.

    Cela génère la classe de service de domaine.

  9. Répétez les étapes précédentes de cette section pour créer un autre service de domaine, mais nommez celui-ci CustomerDomainService.cs (ou CustomerDomainService.vb), sélectionnez l'objet de contexte de données Customer_DataEntities et activez la case à cocher de l'entité Client.

  10. Générez la solution.

  11. Dans le projet client, dans le dossier Generated_Code, ouvrez le fichier du code SharedEntityExample.Web.g.cs généré (vous devrez tout afficher pour voir ce dossier, qui est caché par défaut) et notez la présence d'un SalesDomainContext et d'un CustomerDomainContext. Vous utiliserez les deux objets de contexte de domaine pour charger les données associées.

  12. Fermez le fichier de code généré.

Définition de l'association avec du code dans le projet serveur

Vous avez actuellement deux modèles d'entité distincts et deux services de domaine qui exposent chacun une entité. Vous pourriez charger les données de façon séparée depuis l'une ou l'autre entité en appelant le service de domaine approprié. Mais si vous souhaitez charger des données représentant une combinaison de données des deux entités, vous devez définir le rapport entre ces entités. Les étapes suivantes montrent comment définir ce rapport dans le projet serveur.

Pour définir l'association dans le projet serveur

  1. Cliquez avec le bouton droit sur le projet serveur, sélectionnez Ajouter, puis Nouvel élément.

  2. Dans la liste des catégories, sélectionnez Web, puis sélectionnez le modèle Classe.

  3. Nommez la classe SalesOrderHeader.cs (ou SalesOrderHeader.vb), puis cliquez sur Ajouter.

  4. Dans le fichier de la classe SalesOrderHeader, ajoutez le mot-clé partial à la déclaration de classe.

    Partial Public Class SalesOrderHeader
    
    End Class
    
    namespace SharedEntityExample.Web
    {
        public partial class SalesOrderHeader
        {
        }
    }
    
  5. Ajoutez une propriété nommée Customer qui retourne un objet du type Customer.

    Partial Public Class SalesOrderHeader
        Public Property Customer() As Customer
    
    End Class
    
    namespace SharedEntityExample.Web
    {
        public partial class SalesOrderHeader
        {
            public Customer Customer { get; set; }
        }
    }
    
  6. Ajoutez une instruction using (ou Imports) pour les espaces de noms System.ServiceModel.DomainServices et System.ComponentModel.DataAnnotations.

  7. Ajoutez l'attribut ExternalReferenceAttribute à la propriété Customer.

  8. Ajoutez l'attribut AssociationAttribute à la propriété Customer avec les valeurs suivantes.

    Imports System.ServiceModel.DomainServices
    Imports System.ComponentModel.DataAnnotations
    
    Partial Public Class SalesOrderHeader
        <ExternalReference()> _
        <Association("Sales_Customer", "CustomerID", "CustomerID")> _
        Public Property Customer() As Customer
    
    End Class
    
    using System;
    using System.ServiceModel.DomainServices;
    using System.ComponentModel.DataAnnotations;
    
    namespace SharedEntityExample.Web
    {
        public partial class SalesOrderHeader
        {
            [ExternalReference]
            [Association("Sales_Customer", "CustomerID", "CustomerID")]
            public Customer Customer { get; set; }
        }
    }
    
  9. Générez la solution.

  10. Dans le projet client, dans le dossier Generated_Code, ouvrez le fichier de code généré et notez que la classe SalesOrderHeader contient maintenant une propriété Customer avec les attributs ExternalReferenceAttribute et AssociationAttribute.

  11. Fermez le fichier de code généré.

Chargement des données depuis les deux entités

Les propriétés qui référencent une entité d'un autre contexte de domaine auront la valeur Null jusqu'à ce que l'entité référencée soit chargée dans son contexte de domaine d'origine. L'entité référencée n'est pas chargée automatiquement. Vous devez charger l'entité via son contexte de domaine d'origine avant d'accéder à l'entité ayant des références croisées.

Pour charger des données depuis les deux entités

  1. Dans le projet client, ouvrez le dossier MainPage.xaml.

  2. Depuis la Boîte à outils, faites glisser un contrôle DataGrid dans l'élément Grid.

    Un espace de noms XML et des références aux assemblys de données sont ajoutés.

  3. Donnez au DataGrid le nom SalesGrid et définissez des colonnes de façon à afficher des données combinées comme le montre le XAML suivant.

    <UserControl  x:Class="SharedEntityExample.MainPage"
        xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" 
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <Grid x:Name="LayoutRoot" Background="White">
            <data:DataGrid Name="SalesGrid" AutoGenerateColumns="False">
                <data:DataGrid.Columns>
                    <data:DataGridTextColumn Header="Sales Order ID" Binding="{Binding SalesOrderID}"></data:DataGridTextColumn>
                    <data:DataGridTextColumn Header="Total Due" Binding="{Binding TotalDue}"></data:DataGridTextColumn>
                    <data:DataGridTextColumn Header="Order Date" Binding="{Binding OrderDate}"></data:DataGridTextColumn>
                    <data:DataGridTextColumn Header="Customer First Name" Binding="{Binding Customer.FirstName}"></data:DataGridTextColumn>
                    <data:DataGridTextColumn Header="Last Name" Binding="{Binding Customer.LastName}"></data:DataGridTextColumn>
                </data:DataGrid.Columns>
            </data:DataGrid>
        </Grid>
    </UserControl>
    
  4. Ouvrez le fichier code-behind MainPage.xaml.cs (ou MainPage.xaml.vb).

  5. Ajoutez une instruction using (ou Imports) pour l'espace de noms SharedEntityExample.Web et l'espace de noms System.ServiceModel.DomainServices.Client.

  6. Créez des variables pour les instances de SalesDomainContext et CustomerDomainContext.

    Private salesContext As New SalesDomainContext()
    Private customerContext As New CustomerDomainContext()
    
    private SalesDomainContext salesContext = new SalesDomainContext();
    private CustomerDomainContext customerContext = new CustomerDomainContext();
    
  7. Dans le constructeur, ajoutez une référence entre les objets de contexte de domaine en appelant la méthode AddReference, chargez chaque entité en appelant la méthode Load et paramétrez les entités de ventes sur l'ItemsSource du DataGrid.

    Imports SharedEntityExample.Web
    Imports System.ServiceModel.DomainServices.Client
    
    Partial Public Class MainPage
        Inherits UserControl
    
        Private salesContext As New SalesDomainContext()
        Private customerContext As New CustomerDomainContext()
    
        Public Sub New()
            InitializeComponent()
    
            salesContext.AddReference(GetType(Customer), customerContext)
    
            Dim salesLoadOp = salesContext.Load(salesContext.GetSalesOrderHeadersQuery())
            Dim customerLoadOp = customerContext.Load(customerContext.GetCustomersQuery())
    
            SalesGrid.ItemsSource = salesLoadOp.Entities
        End Sub
    
    End Class
    
    using System;
    using System.Windows.Controls;
    using SharedEntityExample.Web;
    using System.ServiceModel.DomainServices.Client;
    
    namespace SharedEntityExample
    {
        public partial class MainPage : UserControl
        {
            private SalesDomainContext salesContext = new SalesDomainContext();
            private CustomerDomainContext customerContext = new CustomerDomainContext();
    
            public MainPage()
            {
                InitializeComponent();
    
                salesContext.AddReference(typeof(Customer), customerContext);
    
                LoadOperation<SalesOrderHeader> salesLoadOp = salesContext.Load(salesContext.GetSalesOrderHeadersQuery());
                LoadOperation<Customer> customerLoadOp = customerContext.Load(customerContext.GetCustomersQuery());
    
                SalesGrid.ItemsSource = salesLoadOp.Entities;
            }
        }
    }
    
  8. Exécutez la solution.

    Vous verrez une instance du DataGrid qui affiche les données de deux entités dans deux modèles d'entité et deux services de domaine distincts.

Définition de l'association avec du code dans le projet client

Vous pouvez aussi définir l'association entre les entités sur le client, sans avoir à ajouter de code au projet serveur. Cette approche est meilleure si vous préférez éviter d'introduire une nouvelle propriété dans le projet serveur, dont le but est uniquement de parvenir à afficher conjointement les données sur le client.

Pour définir l'association avec du code dans le projet client

  1. Dans le projet serveur, effacez (ou commentez) l'intégralité du fichier SalesOrderHeader.cs (ou SalesOrderHeader.vb) que vous aviez ajouté auparavant.

  2. Générez la solution de façon que le fichier de code généré ne possède plus de propriété Customer sur l'objet SalesOrderHeader.

  3. Dans le projet client, ajoutez un nouveau fichier de Classe nommé SalesOrderHeader.cs (ou SalesOrderHeader.vb).

  4. Dans le fichier de classe SalesOrderHeader, ajoutez le mot-clé partial à la déclaration de classe et modifiez l'espace de noms en SharedEntityExample.Web. (Si vous utilisez Visual Basic, vous pouvez spécifier l'espace de noms Web à l'aide de l'instruction Namespace.)

    Cette classe étend la classe dans le fichier de code généré. La classe d'entité générée possède l'espace de noms du projet serveur.

  5. Ajoutez une instruction using (ou Imports pour Visual Basic) pour les espaces de noms System.ServiceModel.DomainServices, System.ServiceModel.DomainServices.Client, et System.ComponentModel.DataAnnotations.

  6. Pour établir l'association, définissez la propriété Customer ou la classe SalesOrderHeader et marquez-la avec les attributs ExternalReferenceAttribute et AssociationAttribute, comme dans l'exemple de code suivant.

    Imports System.ServiceModel.DomainServices
    Imports System.ServiceModel.DomainServices.Client
    Imports System.ComponentModel.DataAnnotations
    
    Namespace Web
    
        Partial Public Class SalesOrderHeader
            Private _customer As EntityRef(Of Customer)
    
            <ExternalReference()> _
            <Association("Sales_Customer", "CustomerID", "CustomerID")> _
            Public ReadOnly Property Customer() As Customer
                Get
                    If (Me._customer Is Nothing) Then
                        Me._customer = New EntityRef(Of Customer)(Me, "Customer", AddressOf Me.FilterCustomer)
                    End If
    
                    Return Me._customer.Entity
                End Get
            End Property
    
            Private Function FilterCustomer(ByVal entity As Customer) As Boolean
                Return (entity.CustomerID = Me.CustomerID)
            End Function
        End Class
    
    End Namespace
    
    using System;
    using System.Windows.Controls;
    using System.ServiceModel.DomainServices;
    using System.ComponentModel.DataAnnotations;
    using System.ServiceModel.DomainServices.Client;
    
    namespace SharedEntityExample.Web
    {
        public partial class SalesOrderHeader
        {
            private EntityRef<Customer> _customer;
    
            [ExternalReference]
            [Association("Sales_Customer", "CustomerID", "CustomerID")]
            public Customer Customer
            {
                get
                {
                    if (this._customer == null)
                    {
                        this._customer = new EntityRef<Customer>(this, "Customer", this.FilterCustomer);
                    }
    
                    return this._customer.Entity;
                }
            }
    
            private bool FilterCustomer(Customer entity)
            {
                return (entity.CustomerID == this.CustomerID);
            }
        }
    }
    
  7. Appuyez sur F5 pour exécuter la solution.

    L'instance DataGrid qui affiche les données partagées provenant de chacune des entités dans les deux modèles d'entité distincts dans leurs services de domaine respectifs doit maintenant s'afficher dans le navigateur.