Consuming an ADO.NET Data Service from Silverlight
When developing Silverlight line of business (LOB) applications we often need to get at some data from a database. There are various ways to do so. One option that is easy to get started with with is creating an ADO.NET Entity Data Model (EDM) and exposing that entity model using an ADO.NET Data Service.
Getting started
The first thing we need to create is an ASP.NET Web Application. This is basically going to act as a container for our Data Service and our Silverlight LOB application. As you can see below I named the Web Application SLDataService.
Next we need to add the ADO.NET Entity Data Model. I already have a Northwind SQL Server database on my machine and that is the database I am going to expose to I am naming the EDM Northwind.edmx.
When the popup ask if I want to create a new EDM based on an existing database or start from scratch I selected the existing database option and pointed it at my Northwind database. This lets me select the tables I want to import. In this case I am only interested in the Customers table so that is what I am importing. By default the class name will be the same as the table name, i.e. Customers, but as Customer is a more logical name I removed the training “s”.
Next step is creating the ADO.NET Data Service to publish the entity model. Add another item to the project, this time choosing an ADO.NET Data Service and naming it Northwind.svc.
If we open the Northwind.svc.cs file we need to enter a few details before we can proceed. The first thing we need to enter is EDM class name we are going to expose. In this case that is the NorthwindEntities model. Next we need to allow callers to access the EDM. By default nothing is exposed to this is a crucial step that needs to be done in the InitializeService() function! In this case I am going to allow everything, maybe not the best solution in real live 
public class Northwind : DataService<NorthwindEntities>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
}
}
Testing our data service
Now we should be able to test our ADO.NET Data Service in the browser. Start the project and you should see the following in the browser.
Navigate to the following URL http://localhost:4163/Northwind.svc/CustomerSet by adding CustomerSet and you should see the following customer data.
If you see an RSS feed instead of the XML go into settings and disable the feed reading view. BTW the reason the customers data is showing up as an RSS feed is because the ADO.NET Data Services uses the ATOM feed format to transmit its data using a REST approach.
Creating a Silverlight LOB client
The next step is to create a Silverlight client application to consume and display the data. Add a new project the solution of type Silverlight Application and name it SilverlightClient.
When prompted just accept the defaults and add the Silverlight application to the existing SLDataService app. Next we need to add a service reference to the Northwind ADO.NET Data Service. Call it NorthwindService.
Next we need to set up a bit of a user interface to display the list of customers. I kept this really simple and used a ListBox with a DataTemplate like this:
<UserControl x:Class="SilverlightClient.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="500" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<ListBox x:Name="lstCustomers">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CompanyName}" Width="250" />
<TextBlock Text="{Binding City}" Width="100" />
<TextBlock Text="{Binding Country}" Width="100" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
The final step is to load the data from the service and bind this to the ListBox. To do that we need to create an DataServiceContext object of type NorthwindEntities. Unlike a regular service reference the DataServiceContext does not know its own URL by default and we need to be given the URL where the web service is located. Easy enough using the URL of the current page, loaded using HtmlPage.Document.DocumentUri, and the name of the service, Northwind.svc in this case.
Uri uri = new Uri(HtmlPage.Document.DocumentUri, "Northwind.svc");
NorthwindEntities context = new NorthwindEntities(uri);
Using this context object we can do a LINQ query to load some data. Pretty standard stuff except that the asynchronous nature of Silverlight changes the actual loading of the data a bit. Normally you would expect to do something like:
var query = from cust in context.CustomerSet
select cust;
lstCustomers.ItemsSource = query.ToList();
In this case that won’t work and will only result in an System.NotSupportedException with the following message "Specified method is not supported.".
The correct way of doing this is by using a DataServiceQuery object which can load the data asynchronously as follows:
var query = from cust in context.CustomerSet
select cust;
var dsQuery = (DataServiceQuery<Customer>)query;
dsQuery.BeginExecute(
result => lstCustomers.ItemsSource = dsQuery.EndExecute(result),
null);
And the final result looks like this
Not bad at all 
The complete code behind looks like this:
using System;
using System.Data.Services.Client;
using System.Linq;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using SilverlightClient.NorthwindService;
namespace SilverlightClient
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
Uri uri = new Uri(HtmlPage.Document.DocumentUri, "Northwind.svc");
NorthwindEntities context = new NorthwindEntities(uri);
var query = from cust in context.CustomerSet
select cust;
// This doesn't work and will throw an System.NotSupportedException!
// lstCustomers.ItemsSource = query.ToList();
var dsQuery = (DataServiceQuery<Customer>)query;
dsQuery.BeginExecute(
result => lstCustomers.ItemsSource = dsQuery.EndExecute(result),
null);
}
}
}
Visual Studio project sampe code
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu