# Walkthrough: Sharing Entities between Multiple Domain Services

\[ **This document was written for WCF Services Version 1 Service Pack 2 and might not be up to date** \
&#x20;Please see [Release Notes](https://github.com/OpenRIAServices/OpenRiaServices/releases) or [Changelog](https://github.com/OpenRIAServices/OpenRiaServices/blob/main/Changelog.md) for a list of changes since WCF RIA Services ]

In your Open Ria Services application, you may need to display data from a variety of data sources or expose an entity to more than one domain service. For example, an e-commerce Web site may need to integrate data from its order processing system with products from a third-party domain service. Open Ria Services enables this scenario by supporting references between entities from different [DomainContext](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422732.md) types. For more information on the nature and limitations of this feature, see the [Shared Entities](https://openriaservices.gitbook.io/openriaservices/ee707348/ee707356/gg602750) topic.

In this walkthrough, you will be shown two different ways of defining an association between entities in different domain context instances:

* In the first part, the association is defined by adding code in the server project.
* In the second part, the association is defined with code in the client project.

Both approaches to defining the association use the same code on the client to retrieve and display the data.

For illustrative purposes in this walkthrough, you will create two entity models and two domain services for exposing data in the AdventureWorksLT sample database. Typically, you would not create two entity models and two domain services to expose data from a single source. We are using this approach here to simplify the example while learning the technique that you can then use in more complicated scenarios that employ multiple data sources. For another example of displaying related data from a single data source, see [Walkthrough: Displaying Related Data in a Silverlight Business Application](https://openriaservices.gitbook.io/openriaservices/gg602747/ee796241).

## Prerequisites

This and the other walkthroughs presented in the Open Ria Services documentation require several prerequisite programs, such as Visual Studio and the Silverlight Developer Runtime and SDK, be installed and configured properly, in addition to Open Ria Services and the Open Ria Services Toolkit. They also require installing and configuring SQL Server 2008 R2 Express with Advanced Services and installing the AdventureWorks OLTP and LT database.

Detailed instructions for the satisfaction of each of these prerequisites are provided by the topics within the [Prerequisites for Open Ria Services](https://openriaservices.gitbook.io/openriaservices/gg512106) node. Follow the instructions provided there before proceeding with this walkthrough to ensure that you encounter as few problems as possible when working through this Open Ria Services walkthroughs.

## Creating a solution, the data models, and domain services

### To set up a Open Ria Services Solution

1. In Visual Studio, create a new Open Ria Services project by selecting **File**, **New**, and then **Project**.

   The **New Project** dialog box appears.
2. Select the **Silverlight Application** template from the **Silverlight** Templates and name the new project SharedEntityExample.
3. Click **OK**.

   The **New Silverlight Application** dialog box appears.
4. Select the **Enable Open Ria Services** check box at the bottom of the window.
5. Click **OK** to create the solution.

### To create two entity data models

1. In **Solution Explorer**, right-click the server project (SharedEntityExample.Web), select **Add**, and then select **New Item**.

   The **Add New Item** dialog box appears.
2. Select **Data** from the list of **Installed Templates** on the left, and then select the **ADO.NET Entity Data Model** template.
3. Name the new file SalesModel.edmx and click **Add**.

   The **Entity Data Model Wizard** appears.
4. In the **Choose Model Contents** screen, select **Generate from database** and then click **Next**.
5. In the **Choose Your Data Connection** screen, create a data connection to the AdventureWorksLT database.
6. If the AdventureWorksLT database does not appear in the dropdown list, click on **New Connection**, select the correct **Server name**, and then select the **AdventureWorksLT** data base from the drop-down menu in the **Connect to a database** box lower down in the window. Select **Test Connection** button to make sure the database is accessible and click **OK**.
7. Make sure that the **Save entity connection settings in Web.Config as** check box is selected when you are returned to the **Entity Data Model Wizard** and change the value of the entity connection settings to Sales\_DataEntities.
8. Click **Next**.
9. In the **Choose Your Database Objects** screen, select the **SalesOrderHeader** table.
10. Click **Finish**.

    The entity model is created for the table.
11. Repeat the previous steps in this section to create another Entity Data Model for the AdventureWorksLT database, but name it CustomerModel.edmx, change the value of the entity connection setting in Web.config to Customer\_DataEntities, and select the **Customer (SalesLT)** table.
12. Build the solution.
13. Open the code file for the Sales entity model, and notice that the SalesOrderHeader class has a CustomerID property. You will use this property to associate SalesOrderHeader and Customer.

### To create the domain services

1. Right-click the SharedEntityExample.Web server project, select **Add** and **New Item**.
2. In the list of categories, select **Web** and then select the **Domain Service Class** template.
3. Name the class SalesDomainService.cs (or SalesDomainService.vb).
4. Click **Add**.

   The **Add New Domain Service Class** dialog box appears.
5. Make sure the **Enable client access** check box is selected.
6. From the **Available DataContext/ObjectContext classes** list, select **Sales\_DataEntities (Entity Framework)** data context object.

> \[!TIP] If you gave your data connection a different name when creating the entity model, select the data context object that contains the SalesOrderHeader entity.

1. Under **Entities**, select the **SalesOrderHeader** entity check box.
2. Click **OK**.

   This generates the domain service class.
3. Repeat the previous steps in this section to create another domain service, but name it CustomerDomainService.cs (or CustomerDomainService.vb), select the **Customer\_DataEntities** data context object, and select the **Customer** entity check box.
4. Build the solution.
5. In the client project, in the Generated\_Code folder, open the generated code SharedEntityExample.Web.g.cs file (you will have to show all to see this file which is hidden by default) and notice that there is a SalesDomainContext and a CustomerDomainContext. You will use both domain context objects to load the associated data.
6. Close the generated code file.

## Defining the association with code in the server project

You currently have two separate entity models and two domain services that each exposes one entity. You could load data from either entity separately by calling the appropriate domain service. But to load data that is a combination of data from both of the entities, you must define the relationship between these entities. The following steps show how to define that relationship in the server project.

### To define the association in the server project

1. Right-click the server project, select **Add** and **New Item**.
2. In the list of categories, select **Web** and then select the **Class** template.
3. Name the class SalesOrderHeader.cs (or SalesOrderHeader.vb) and then click **Add**.
4. In the SalesOrderHeader class file, add the partial keyword to the class declaration.

   ```
   Partial Public Class SalesOrderHeader

   End Class
   ```

   ```csharp
   namespace SharedEntityExample.Web
   {
       public partial class SalesOrderHeader
       {
       }
   }
   ```
5. Add a property named Customer that returns an object of the Customer type.

   ```
   Partial Public Class SalesOrderHeader
       Public Property Customer() As Customer

   End Class
   ```

   ```csharp
   namespace SharedEntityExample.Web
   {
       public partial class SalesOrderHeader
       {
           public Customer Customer { get; set; }
       }
   }
   ```
6. Add a using (or Imports) statements for the [OpenRiaServices](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422155.md) and [System.ComponentModel.DataAnnotations](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/cc490428.md) namespaces.
7. Add the [ExternalReferenceAttribute](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422861.md) attribute to the Customer property.
8. Add the [AssociationAttribute](https://msdn.microsoft.com/en-us/library/Dd382136) attribute to the Customer property with the following values.

   ```
   Imports OpenRiaServices
   Imports System.ComponentModel.DataAnnotations

   Partial Public Class SalesOrderHeader
       <ExternalReference()> _
       <Association("Sales_Customer", "CustomerID", "CustomerID")> _
       Public Property Customer() As Customer

   End Class
   ```

   ```csharp
   using System;
   using OpenRiaServices;
   using System.ComponentModel.DataAnnotations;

   namespace SharedEntityExample.Web
   {
       public partial class SalesOrderHeader
       {
           [ExternalReference]
           [Association("Sales_Customer", "CustomerID", "CustomerID")]
           public Customer Customer { get; set; }
       }
   }
   ```
9. Build the solution.
10. In the client project, in the Generated\_Code folder, open the generated code file and notice that the SalesOrderHeader class now contains a Customer property with the [ExternalReferenceAttribute](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422861.md) and [AssociationAttribute](https://msdn.microsoft.com/en-us/library/Dd382136) attributes.
11. Close the generated code file.

## Loading the data from both entities

Properties that reference an entity from another domain context will be null until the referenced entity is loaded in its original domain context. The referenced entity is not automatically loaded. You must load the entity through its origin domain context before accessing the cross-referenced entity.

### To load the data from both entities

1. In the client project, open the MainPage.xaml file.
2. From the Toolbox, drag a DataGrid control to within the Grid element.

   An XML namespace and references to Data assemblies are added.
3. Name DataGridSalesGrid and define columns to display the combined data as shown in the following XAML.

   ```
   <UserControl  x:Class="SharedEntityExample.MainPage"
       xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://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. Open the code-behind file MainPage.xaml.cs (or MainPage.xaml.vb).
5. Add a using (or Imports) statement for the SharedEntityExample.Web namespace and the [OpenRiaServices.Client](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422479.md) namespace.
6. Create variables for instances of the SalesDomainContext and CustomerDomainContext.

   ```
   Private salesContext As New SalesDomainContext()
   Private customerContext As New CustomerDomainContext()
   ```

   ```csharp
   private SalesDomainContext salesContext = new SalesDomainContext();
   private CustomerDomainContext customerContext = new CustomerDomainContext();
   ```
7. In the constructor, add a reference between the domain context objects by calling the AddReference method, load each entity by calling the Load method, and set the sales entities to the ItemsSource of the DataGrid.

   ```
   Imports SharedEntityExample.Web
   Imports OpenRiaServices.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
   ```

   ```csharp
   using System;
   using System.Windows.Controls;
   using SharedEntityExample.Web;
   using OpenRiaServices.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. Run the solution.

   You will see a DataGrid instance that displays data from two entities in two separate entity models and domain services.

## Defining the association with code in the client project

You can also define the association between the entities on the client, without having to add any code to the server project. This approach is better if you preferable not to introduce a new property in the server project whose only purpose is to achieve the client objective of displaying the data jointly.

### To define the association with code in the client project

1. In the server project, delete (or comment out) the entire SalesOrderHeader.cs (or SalesOrderHeader.vb) file that you previously added.
2. Build the solution so that the generated code file no longer has a Customer property on the SalesOrderHeader object.
3. In the client project, add a new Class file named SalesOrderHeader.cs (or SalesOrderHeader.vb).
4. In the SalesOrderHeader class file, add the partial keyword to the class declaration, and change the namespace to SharedEntityExample.Web. (If you are using Visual Basic, you can specify the Web namespace by using the Namespace statement.)

   This class extends the class in the generated code file. The generated entity class has the namespace from the server project.
5. Add a using (or Imports for Visual Basic) statement for the [OpenRiaServices](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422155.md), [OpenRiaServices.Client](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422479.md), and [System.ComponentModel.DataAnnotations](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/cc490428.md) namespaces.
6. To establish the association, define the Customer property or the SalesOrderHeader class and mark it with the [ExternalReferenceAttribute](https://github.com/OpenRIAServices/OpenRiaServices/tree/086ea8c8fcb115000749be6b2b01cd43bb95bf80/docs/ff422861.md) and [AssociationAttribute](https://msdn.microsoft.com/en-us/library/Dd382136) attributes as shown in the following code sample.

   ```
   Imports OpenRiaServices
   Imports OpenRiaServices.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
   ```

   ```csharp
   using System;
   using System.Windows.Controls;
   using OpenRiaServices;
   using System.ComponentModel.DataAnnotations;
   using OpenRiaServices.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. Hit F5 to run the solution.

   The DataGrid instance that displays data shared out from each of the entities in the two separate entity models in their respective domain services should now display in the browser.
