I wanted to continue with the enhancements to my  Mix09 talk “building business applications with Silverlight 3”.   In this section I am going to show how to get data from a REST based web services rather than directly using Entity Framework or Linq to Sql. 

Let’s focus on the cloud source of data.  We will use the same sample from the previous parts and change only the data access part to go against ADO.NET Data Services as the data store.   

image

This pattern might be useful if you do not control your database directly and need to go through a services layer to access it. 

The demo requires (all 100% free and always free):

  1. VS2008 SP1 (Which includes Sql Express 2008)
  2. Silverlight 3 RTM
  3. .NET RIA Services July '09 Preview  (optional for this part of the demo)

Also, download the full demo files and check out the running application

Start with the MyApp project from one of the previous parts.  In the server project, delete the northwind.mdf and the Northwind.edmx files.

Add a new project to the solution to hold the data service.  I used an ASP.NET Web Application project and called it MyApp.Service…

image

Next, add the Northwind.mdf file to the app_data folder of this new project and create an entity framework model as we showed in part 2.

Now let’s add our REST based service. 

image

Here we set up the DataService to use the EntityFramework provider then we enable access… notice the “*” is more of a demo mode sort of thing, the best practice here is to list the tables directly. 

public class SuperEmployeeDataService : DataService< NORTHWNDEntities >
{
    public static void InitializeService(IDataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
    }
}

Now we are good to go with our service.. To test it set it as the start up project and hit F5… 

image

We are all set to consume this now from RIA Services…  Notice all the above is standard ADO.NET Data Services work… Learn more about ADO.NET Data Services.

Now, let’s get into the meat with RIA Services..  Go back to the web project and add a services reference to the service we just created.

image

 

First let’s go into SuperEmployeeDomainService.metadata.cs and tweak this class to work with our new service reference. Basically you just need to make sure it is a partial class of the proxy SuperEmployee class from our service reference.  Do this by changing the namespace to MyApp.Web.SuperEmployeeDataServiceReference.  This class gives you a chance to add validation metadata and other information to make the client consumption more clean.   We will validate these on the client and before the data gets pushed back to the service.    Some examples:

[ReadOnly(true)]
[Key]
public int EmployeeID;
 
[RegularExpression("^(?:m|M|male|Male|f|F|female|Female)$", 
    ErrorMessage = "Gender must be 'Male' or 'Female'")]
public string Gender;
 
[Range(0, 10000,
    ErrorMessage = "Issues must be between 0 and 1000")]
public Nullable<int> Issues;

 

Now we need to make our SuperEmployeeDomainContext work against this new service. 

[EnableClientAccess()]
public class SuperEmployeeDomainService : DomainService
{
    NORTHWNDEntities Context = new NORTHWNDEntities(
        new Uri("http://localhost:40694/SuperEmployeeDataService.svc/"));

Notice here we use the DomainService base class rather than the EFDomainSerivce helper… 

 

Methods such as GetSuperEmployee() work with no change!  But they are now going over our REST based service to get to the database. 

public IQueryable<SuperEmployee> GetSuperEmployees()
{
    return this.Context.SuperEmployeeSet
               .Where(emp=>emp.Issues>100)
               .OrderBy(emp=>emp.EmployeeID);
}

UpdateSuperEmployee took a bit more tweaks as we need to propagate changes over to instances that the ADO.NET client library is tracking.  

public void UpdateSuperEmployee(SuperEmployee currentSuperEmployee)
{
    var q = from emp in Context.SuperEmployeeSet
            where emp.EmployeeID == currentSuperEmployee.EmployeeID
                select emp;
 
    var e = q.FirstOrDefault();
    e.Name = currentSuperEmployee.Name;
    e.Gender = currentSuperEmployee.Gender;
    e.Issues = currentSuperEmployee.Issues;
    e.LastEdit = currentSuperEmployee.LastEdit;
    e.Origin = currentSuperEmployee.Origin;
    e.Publishers = currentSuperEmployee.Publishers;
    e.Sites = currentSuperEmployee.Sites;
    
    Context.UpdateObject(e);
}

Finally, we need to override Submit…  What this does is gives us a chance to call PersistChangeSet() after all the changes in the change set have been processed (the call the the base method does that).

protected override void PersistChangeSet(ChangeSet changeSet)
{
    base.PersistChangeSet(changeSet);
    this.Context.SaveChanges();
}

Hit F5 and we are done!  We now have exactly the same app, but with data coming from a service rather than directly from a data base. 

Also notice how easy this was to move from one model to another.. That is another powerful reason to follow the RIA Services model.. it enables you to more easily change backend data sources without changing a lot of code on the client.

image