I recently had a situation with a client who had a requirement to use Silverlight 4.0 with RIA Services for an application under development. I've used WCF RIA Services on and off and have a bit of a love-hate thing with them (they wreak havoc on ReSharper's Adjust Namespaces feature, for instance, which is an OCD habit of mine), but using them really did make sense in this client's case.

Anyway... The client's application had to interface with a legacy database and no schema changes are permitted (sound familiar?). The database was a monster, with over 300 tables, 255 columns per table in some cases, no referential integrity constraints and eight-character field and table names.

If I'd had a month just to map it, I'd have suggested NHibernate for its ability to tie itself into knots to allow arbitrary key constraints and other cleverness. As I just don't have a month, however, the client's going with EF because it automatically builds a map that makes me cry a beautiful map of the database schema as-is.

Adding a Domain Service based on an EF data layer is also trivial - RIA Services has a magical code generator that builds the entire suite of CRUD WCF services for us and it's entirely possible that we'll never need to tweak them.

image

If you have a look at the SilverlightApp project at the top, you'll see a "Generated_Code" directory that contains all of the generated proxy code for all the domain services advertised by the SilverlightApp.Web project.

The catch is that it generates proxy code for every single class advertised by EF (although it's selectable, in this case it's actually required), which in this case results in approximately 300,000 lines of code.

The Problem

It takes a long time to compile 300,000 lines (about 10Mb) of code, especially every single time a completely unrelated change is made to the UI.

Enter RIA Services Class Libraries.

RIA class libraries are not your garden-variety of class library. They're not particularly well documented and are fairly unintuitive. If you follow the standard directions you'll miss the really clever part, which is the part that makes it worth-while to use them in the first place.

The key is that we want all the generated code in a library that we don't compile every single time we make a UI change. So... how do we do that?

Creating and using a WCF RIA Services Class Library

1. Create your Silverlight project (use the Business Application template if you don't have any pressing need not to - it's great).

2. Add a new "WCF RIA Services Class Library" to your solution. This will create two projects: the class library itself and another web project to host it in.

image

3. Add a reference from your existing web site to your new class library's web site.

4. Add your domain services into your class library's web site instead of your main web site. For the sake of an example I've added a domain service around pet ownership, with Pet and Owner entities.

You're not done yet! This is the part where it will all actually work, so people tend to forget the next step. I'll show you that in a minute.

Let's have a look in the Generated_Code folder in our main Silverlight app at this point. Firstly, make sure that you've checked the "Show All Files" button for the SilverlightApp project so that you can see the Generated_Code directory:

image image

Open the SilverlightApp.Web.g.cs file and have a look. You should see something like this:

image

Note the definition of a proxy class for the "Owner" entity. Hang on a minute, though - this class was supposed to be in the class library - we don't want it in our main application. The whole point of this exercise was to not have all this generated code in our main Silverlight application as it takes too long to compile. The next step then:

5. Add a reference from your Silverlight app to your Silverlight class library. This is the obvious step but it's the one that lots of people miss, hence this blog post.

The WCF RIA code generator is actually very clever and it works out which entities you have proxy code for already to and only generates code for the ones you're missing.

Once you add the reference, if you leave the generated code file open, this is what you should see:

image

Ooh! No proxy code for our entities! Our compilation times just plummeted Smile