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
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.
Sélectionnez le modèle Application Silverlight dans les modèles Silverlight et nommez le nouveau projet SharedEntityExample.
Cliquez sur OK.
La boîte de dialogue Nouvelle application Silverlight s'ouvre.
Activez la case à cocher Activer les services RIA WCF au bas de la fenêtre.
Cliquez sur OK pour créer la solution.
Pour créer deux Entity Data Models
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.
Sélectionnez Données dans la liste des Modèles installés, gauche, puis sélectionnez le modèle Entity Data Model ADO.NET.
Nommez le nouveau fichier SalesModel.edmx, puis cliquez sur Ajouter.
L'Assistant EDM s'affiche.
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.
Sur l'écran Choisir votre connexion de données, créez une connexion de données à la base de données AdventureWorksLT.
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.
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.
Cliquez sur Suivant.
Sur l'écran Choisir vos objets de base de données, sélectionnez la table SalesOrderHeader.
Cliquez sur Terminer.
Le modèle d'entité est créé pour la table.
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).
Générez la solution.
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 associerSalesOrderHeader
etCustomer
.
Pour créer les services de domaine
Cliquez avec le bouton droit sur le projet serveur SharedEntityExample.Web, sélectionnez Ajouter, puis Nouvel élément.
Dans la liste des catégories, sélectionnez Web, puis sélectionnez le modèle Classe DomainService.
Nommez la classe SalesDomainService.cs (ou SalesDomainService.vb).
Cliquez sur Ajouter.
La boîte de dialogue Ajouter une nouvelle classe de service de domaine s'ouvre.
Assurez-vous que la case à cocher Activer l'accès client est activée.
Dans la liste Classes DataContext/ObjectContext disponibles, sélectionnez l'objet de contexte de données Sales_DataEntities (Entity Framework).
Conseil : 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
.Sous Entités, activez la case à cocher de l'entité SalesOrderHeader.
Cliquez sur OK.
Cela génère la classe de service de domaine.
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.
Générez la solution.
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'unCustomerDomainContext
. Vous utiliserez les deux objets de contexte de domaine pour charger les données associées.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
Cliquez avec le bouton droit sur le projet serveur, sélectionnez Ajouter, puis Nouvel élément.
Dans la liste des catégories, sélectionnez Web, puis sélectionnez le modèle Classe.
Nommez la classe SalesOrderHeader.cs (ou SalesOrderHeader.vb), puis cliquez sur Ajouter.
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 { } }
Ajoutez une propriété nommée
Customer
qui retourne un objet du typeCustomer
.Partial Public Class SalesOrderHeader Public Property Customer() As Customer End Class
namespace SharedEntityExample.Web { public partial class SalesOrderHeader { public Customer Customer { get; set; } } }
Ajoutez une instruction using (ou Imports) pour les espaces de noms System.ServiceModel.DomainServices et System.ComponentModel.DataAnnotations.
Ajoutez l'attribut ExternalReferenceAttribute à la propriété
Customer
.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; } } }
Générez la solution.
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.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
Dans le projet client, ouvrez le dossier MainPage.xaml.
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.
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>
Ouvrez le fichier code-behind MainPage.xaml.cs (ou MainPage.xaml.vb).
Ajoutez une instruction using (ou Imports) pour l'espace de noms
SharedEntityExample.Web
et l'espace de noms System.ServiceModel.DomainServices.Client.Créez des variables pour les instances de
SalesDomainContext
etCustomerDomainContext
.Private salesContext As New SalesDomainContext() Private customerContext As New CustomerDomainContext()
private SalesDomainContext salesContext = new SalesDomainContext(); private CustomerDomainContext customerContext = new CustomerDomainContext();
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; } } }
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
Dans le projet serveur, effacez (ou commentez) l'intégralité du fichier SalesOrderHeader.cs (ou SalesOrderHeader.vb) que vous aviez ajouté auparavant.
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'objetSalesOrderHeader
.Dans le projet client, ajoutez un nouveau fichier de Classe nommé SalesOrderHeader.cs (ou SalesOrderHeader.vb).
Dans le fichier de classe
SalesOrderHeader
, ajoutez le mot-clé partial à la déclaration de classe et modifiez l'espace de noms enSharedEntityExample.Web
. (Si vous utilisez Visual Basic, vous pouvez spécifier l'espace de nomsWeb
à 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.
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.
Pour établir l'association, définissez la propriété
Customer
ou la classeSalesOrderHeader
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); } } }
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.