Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Silverlight 4, Ria Services, and Entity Framework Complex Types

0.00/5 (No votes)
9 Mar 2011 1  
How to use complex types on the client.

Introduction

This article will demonstrate how to build a Silverlight 4 application that uses (Entity Framework) Complex Types at the client level (through WCF services).

Background

Before Silverlight 4, it wasn't possible to use complex types on the client, but now, Silverlight 4 can use RIA services to access (Complex) types that the Entity Framework creates. In previous versions of Silverlight, it was possible to access simple entity types but not complex types.

Using the code

Setting up the sample database

If you do not have Microsoft's Northwind database installed on your database server, you can download the script here (download script - 238 KB). Log into your SQL Server Management Studio and open a new query analyzer window, and run the unzipped script to create the database (including data) that is used in the Data Access Layer (DAL) within the overall project.

Create a new (empty) project and add three solution folders, for the data access layer, WCF service, and finally the Silverlight client.

Creating the Data Access Layer (Entity Model) project

Create the data access layer DLL by adding a new Class Library to the 'data access layer' solution in the project.

SL4RiaComplexTypes/1_Create_Data_Access_Layer.jpg

Add an entity framework model to the DAL:

SL4RiaComplexTypes/2_Create_Entity_Framework.jpg

Select the Stored Procedure 'Employee Sales by Country' to the entity model. This Stored Procedure will be used as it will return a complex type (fields from multiple tables).

SL4RiaComplexTypes/3_EFChooseDataObjects.jpg

Bring up the 'Model View' browser so that we can then easily navigate to the entity model.

Create\import the C# function that will represent the method to call the entity method in the DAL.

SL4RiaComplexTypes/5_CreateFunctionToCallSproc.jpg

Create the complex type (class) for the Stored Procedure.

SL4RiaComplexTypes/4_Create_Complex_Type.jpg

Your DAL project structure should look like this:

SL4RiaComplexTypes/6_EntityFrameworkProjectStructure.jpg

Creating the WCF Service project

Add a new WCF service to the WCF solution folder in the project.

SL4RiaComplexTypes/9_Create_Wcf_Service.jpg

Add a reference to the data access layer project in your references:

SL4RiaComplexTypes/10_Add_DAL_dll_To_WCF.jpg

That is your newly added DAL project in your WCF project.

Add the following code to the IOrdersService class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using OrdersAccessLayer;
 
namespace WcfOrdersService
{ 
    [ServiceContract]
    public interface IOrdersService
    {
        /// <summary>
        /// Gets the order details data.
        /// </summary>
        /// <param name="start">The start.</param>
        /// <param name="end">The end.</param>
        /// <returns>A collection of complex type classes
        ///         'Employee_Sales_by_Country_Result'</returns>
        [OperationContract]
        List<Employee_Sales_by_Country_Result> 
           GetOrderDetailsData(DateTime start, DateTime end);      
    }
}

Add the following code to the OrdersService class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using OrdersAccessLayer;
 
namespace WcfOrdersService
{    
    public class OrdersService : IOrdersService
    {
      /// <summary>
      /// A reference to the controller class in the DAL project
      /// </summary>
      private OrdersController orderCtrl;
 
      /// <summary>
      /// Initializes a new instance of the <see cref="OrdersService"/> class.
      /// </summary>
      public OrdersService()
      {
          orderCtrl = new OrdersController();
      }
 
      /// <summary>
      /// Gets the order details data.
      /// </summary>
      /// <param name="start">The start.</param>
      /// <param name="end">The end.</param>
      /// <returns></returns>
        public List<Employee_Sales_by_Country_Result> 
               GetOrderDetailsData(DateTime start, DateTime end)
        {
            return this.orderCtrl.GetOrderDetails(start, end);
        }
    }
}

Compile the service before adding it to the Silverlight project below.

Creating the Silverlight 4 Client project

Create a new Silverlight project:

SL4RiaComplexTypes/12_CreateSilverlightApplication.jpg

Enable the Silverlight project for RIA services and assign it the OrdersService service.

SL4RiaComplexTypes/13_Enable_Ria_Services.jpg

Add a reference to the WCF service:

SL4RiaComplexTypes/14_Add_WCF_Ref_To_SL.jpg

The Silverlight project after adding the service reference:

SL4RiaComplexTypes/15_SL_Structure_After_Adding_WCF_Service.jpg

Add the following code to the code-behind for the MainPage.cs. Notice that in the method SaveScheduleCompleted, there is some LINQ performed on the collection of (entity class) 'Employee_Sales_By_Country_Result'. Thus we are able to create a class in the Entity Framework and also be able to use it in the client.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Silverlight4Console.OrdersServiceReference;
using System.ServiceModel;
 
namespace Silverlight4Console
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            this.LoadOrderDetails();
        }
 
        private void LoadOrderDetails()
        {
            try
            {
                DateTime start = DateTime.Parse("1997-01-01");
                DateTime end = DateTime.Parse("1997-01-31");
 
                OrdersServiceReference.OrdersServiceClient ordersService = 
                  new OrdersServiceReference.OrdersServiceClient();
 
                ordersService.GetOrderDetailsDataAsync(start, end);
                ordersService.GetOrderDetailsDataCompleted += 
                  new EventHandler<GetOrderDetailsDataCompletedEventArgs>(
                  SaveScheduleCompleted);
            }
            catch (FaultException fe)
            {
                Console.WriteLine(fe.Message);
                Console.WriteLine("stack trace");
                Console.WriteLine(fe.StackTrace);
                Console.ReadLine();              
            }
            catch (CommunicationException commProblem)
            {
                if (commProblem.InnerException is FaultException)
                {
                    Console.WriteLine("An unknown exception was received. " + 
                                      commProblem.InnerException.Message);
                    Console.ReadLine();
                    return;
                }
                else
                {
                    Console.WriteLine("There was a communication problem. " + 
                                      commProblem.Message);
                    Console.WriteLine(commProblem.StackTrace);
                }
            }
        }
 
        /// <summary>
        /// Saves the schedule completed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see
        ///    cref="RiaConsole.TemplateService.SaveScheduleCompletedEventArgs"/>
        ///    instance containing the event data.</param>
        private void SaveScheduleCompleted(object sender, 
                     GetOrderDetailsDataCompletedEventArgs e)
        {                        
            this.personDataGrid.ItemsSource = e.Result.Where(ord=>ord.SaleAmount>2000);
        }
    }
}

Add the following XAML code to the MainPage (a simple grid to bind\display order results):

<UserControl x:Class="Silverlight4Console.MainPage"
    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" 
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
 
    <Grid x:Name="LayoutRoot" Background="White">
        <sdk:DataGrid AutoGenerateColumns="true" VerticalAlignment="Center" 
          HorizontalAlignment="Center" Height="100" 
          Margin="57,66,0,0" Name="personDataGrid" Width="auto" />
    </Grid>
</UserControl>

Here is the overall project structure:

SL4RiaComplexTypes/16_SolutionStructure.jpg

Screen output

SL4RiaComplexTypes/Grid.jpg

Points of Interest

Just as a side note, I found it easier to bind the Silverlight application to the WCF service (enabling RIA services), by designing the data access layer, WCF service, and then creating the Silverlight application - I found that creating the Silverlight application first with no RIA service to bind to (but still enabling RIA services) meant that it didn't pick up the services when I later enabled them.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here