I’ve been writing a lot of Silverlight applications as of late that make extensive use of the new .NET RIA Services framework. A common pattern that I’ve ran into is the initial loading of data when a new page in the application has been navigated to. Typically each page requires data from more than one table and as such results in my having to issue multiple Load() calls against my DomainContext. These calls all run in an async fashion with no guaranteed order of completion. In previous versions of RIA Services this meant that as a developer you needed to handle all of the multiplexing issues yourself, typically by creating some scheme for using the userState parameter in the load call to coordinate the de-multiplexing inside of the DomainContext’s Loaded event callback.
The July 2009 CTP of RIA Services changes all of that however. We’ve changed the API to allow each Load() call to specify it’s own callback that will only be called once and only in association with that one specific Load() call (that is, we handle the de-multiplexing for you now). The new Load API now looks like this (in it’s most verbose form):
public LoadOperation<TEntity> Load<TEntity>(EntityQuery<TEntity> query, MergeOption mergeOption,
Action<LoadOperation<TEntity>> callback, object userState) where TEntity : Entity;
This means that you can now specify a per Load callback delegate that will get called as soon as that particular load call is done processing. Additionally, instead of returning VOID as we did in prior CTPs, we now return a LoadOperation class that represents the async load operation and it’s state. For those of you that prefer the eventing pattern over the callback pattern (or if your application has a situation where you need to have multiple listeners), this class comes with a handy dandy Completed event that you can sign up for. And it’s this handy dandy event that’s going to allow us to build a batch manager.
Per call notifications are great for solving the de-multiplexing issue, but typically there is also processing that needs to be performed once all of the data necessary for a page has been loaded. I found myself writing to track the number of outstanding load calls so I would know when to execute this final processing code. I’ve moved all that logic into a simple reusable batch manager class that is shown below. Using this batch manager you can issue as many Load() calls as you want and still receive a single aggregate callback when they have all completed, even if some of them fail along the way (more on that later).
using System;
using System.Collections.Generic;
using System.Windows.Ria.Data;
namespace BusinessApplication1
{
/// <summary>
/// Simple LoadOperation batch manager
/// </summary>
/// <remarks>
/// This class allows you to start multiple load operations in parallel and still received a single
/// 'complete' action callback once all work is done. Load operation failures are also aggregated
/// and will be made available as part of the completion action callback.
/// </remarks>
public class DomainContextLoadBatch
{
private List<LoadOperation> _pendingOperations = new List<LoadOperation>();
private List<LoadOperation> _failedOperations = new List<LoadOperation>();
private Action<DomainContextLoadBatch> _completeAction;
/// <summary>
/// Expose the count of failed operations
/// </summary>
public int FailedOperationCount { get { return _failedOperations.Count; } }
/// <summary>
/// Expose an enumerator for all of the failed operations
/// </summary>
public IEnumerable<LoadOperation> FailedOperations { get { return _failedOperations; } }
/// <summary>
/// Public constructor
/// </summary>
/// <param name="completeAction"></param>
public DomainContextLoadBatch(Action<DomainContextLoadBatch> completeAction)
{
this._completeAction = completeAction;
}
/// <summary>
/// Used to add an operation to the batch
/// </summary>
/// <param name="loadOperation"></param>
public void Add(LoadOperation loadOperation)
{
loadOperation.Completed += new EventHandler(loadOperation_Completed);
_pendingOperations.Add(loadOperation);
}
/// <summary>
/// Processes each operation as it completes and checks for errors
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void loadOperation_Completed(object sender, EventArgs e)
{
LoadOperation loadOperation = sender as LoadOperation;
_pendingOperations.Remove(loadOperation);
loadOperation.Completed -= new EventHandler(loadOperation_Completed);
if (loadOperation.Error != null)
_failedOperations.Add(loadOperation);
CheckForComplete();
}
/// <summary>
/// Called to check for all operations being complete and to fire our completed action
/// </summary>
private void CheckForComplete()
{
if (_pendingOperations.Count > 0)
return;
if (_completeAction != null)
{
_completeAction(this);
_completeAction = null;
}
}
}
}
The new Load API makes managing batched load calls fairly easy and as you can see there’s not a lot of code here. Additionally it doesn’t take much code to use the batch manager either. Here’s a sample code snippet of how you would use this in one of your pages.
private DomainContext1 domainContext = new DomainContext1();
public MainPage()
{
InitializeComponent();
DomainContextLoadBatch batch = new DomainContextLoadBatch(DataLoadComplete);
batch.Add(domainContext.Load(domainContext.GetUsersQuery()));
batch.Add(domainContext.Load(domainContext.GetUserRolesQuery()));
batch.Add(domainContext.Load(domainContext.GetDisciplinesQuery()));
}
private void DataLoadComplete(DomainContextLoadBatch batch)
{
if (batch.FailedOperationCount > 0)
{
// Do Error handling
}
else
{
// Fill out the UI with the data
}
}
That’s it, typically just one extra line of code is all you need to manage your batched load calls. Notice also that we did not touch the actual Load() call itself, so the per call delegate as well as the userState parameter are still wide open for your application to use however it sees fit. A couple things to note about the DomainContextLoadBatch class:
- Currently it only works for Load() calls. It would need to be extended if you run into a situation where you have multiple Submit() calls that you’d like to batch together (although, I’ve never actually ran into a situation that requires this yet).
- There’s no thread management… that is this class is not thread safe. It assumes that all of your Load calls happen on the same thread and that is also the same thread that you call batch.Add() on.
- The Complete callback gets called regardless of any errors, so be sure and check the FailedOperationCount property in your callback to deal with any failed load calls (the actual failed load calls are available using the FailedOperations enumeration).
There you go, a simple batch manager for .NET RIA Services. Until next time, happy querying (and batching)!
I've been OOF on vacation (Hawaii, where it's warm!). But I'm back now and here's a few new sample applications that I've come across recently as I've been surfing around looking at various things that folks are doing.
End to End Data Centric App - A quick walk through of building a data centric SL application
Calendar and DatePicker Starter Guides - Some quick starter guides on a couple of our new controls
Dynamic Image Generation - Shows how to dynamically generate images at runtime in SL
Running SL as Standalone Full Trust Application - Shows how to run an SL application in full trust
Jesse Liberty Silverlight Tutorials - An indepth series on Silverlight
Game Programming with Silverlight - A series of blogs on game programming in SL
Writing a Templated Silverlight Control: An Shawn Burkepost that details how to create a custom templated Silverlight control
Using the Silverlight DataGrid - A nice introduction to using the new SL data grid
A few astute readers have already found a couple issues and sent in a few ideas. I've updated the calculator sample, both the live version and the code download.
Included in the update:
- A few bug fixes
- Larger toolbar buttons (some folks didn't notice them at first)
- I've added a Unit Test project and some unit tests.
- A new skin has been added (the style shamelessly stolen from Corrina's blog, but she's on vacation so I don't feel too bad about it :)
Adding Unit Tests
If you're interested in knowing more about the Unit Test framework and getting it up and running, see Jeff Wilcox's blog on getting the bits and some VS templates.
I implemented my calculator in several layers, separated by interface definitions as shown here:
This allowed me to accomplish 2 things. First, the skinning I wanted and second the ability to isolate the individual parts of my application for testing. So if you look at the test project that I've added to the code zip, you'll see that there are tests that isolate just the commands themselves, tests for just the numeric stack itself and tests that work on the engine in isolation (not I did not do full test coverage, just a smattering of samples). Still working on figuring out how one would test the skin in isolation (we need a good UI automation package for Silverlight! :)
OK so I finally found some time to start playing around with SL2 B1 in earnest this last weekend. The results? A Silverlight Calculator. I don’t know why but a calculator has always been my HelloWorld, every new programming language or UI stack I learn always starts with a calculator. Anyway you can try out the live version of it here and download the full source code here. You can find some good instructions on how to get up and running on Silverlight here if needed.
A Basic Calculator

A quick overview of the things I explored during this process.
Some known issues/ToDos:
· Resetting the AddIns is a fairly jarring experience right now (since Assemblies cannot be unloaded, a full page refresh is done to cycle the AppDomain). At a minimum I need to have an Are you sure? MessageBox (but SL has no such thing yet). Ideally you should be able to turn off the add-ins one at a time and the calculator would just quit using the extension even though they still exist in the domain.
· No versioning support for the AddIns. If you want to get a new version of your AddIn loaded you currently have to unload all the AddIns, reset the AppDomain and then reload your addins.
· Application Errors are either ignored or unhandled right now. I have to figure out a good model for dealing with these things.
· Currently only text is supported in the Command Buttons, I need to explore the wonderful world of loading/parsing XAML at runtime and allow commands to have more sophisticated button views. Styling is currently putting a serious crimp in these efforts, but we’ll see where it goes.
Anything else? Comments? Ideas on additional areas/techniques to explore here?
Looks like it’s time to finally jump into the blog pool. I’ve been thinking for some time now about what I wanted in a blog and how I could contribute value to the .NET blogging community. Recently a couple big changes have happened that have provided clarity to that thinking, and so here I am. First, the release of Silverlight 2 Beta 1 at Mix this year as kicked off a big wave of development efforts in and around this technology. More specifically, a wave of interest in the Rich Internet Application (RIA) space. The second big change was a recent career move here at Microsoft that has positioned me as a Dev Lead here on the UIFX team… right smack dab in the middle of that Silverlight/RIA wave. So now all of sudden I’ve got something big and interesting to talk about and just as importantly I’ve got a keen interest in listening, learning and trading experiences around this amazing technology.
Who am I?
So, who am I and what do I want to talk about? Well, as you might have noticed I’m a Microsoft employee and have been for almost 18 years now, currently working in the UIFX group as a Dev Lead. I started with Microsoft back in 1990 working in Developer Support helping ISVs write applications for Windows 3.0. Back then MDI and DDE where the coolest 3 letter acronyms on the block, but it didn’t take long for things like OLE, COM and MFC to become all the rage. By the time 1995 rolled along things like MSN, CIS and AOL where changing the landscape of computer usage, bringing real world uses for the PC into the home and setting up a broad base of users just waiting for the Internet explosion and the ubiquity of high-speed access to the rest of the world from the comfort of your own living room. CGI, HTML and ASP became all the rage and not too long after that .NET, the CLR and ASP.NET flew on to the scene and ushered in a new era of productivity for developers.
So where am I going with all this? Well, all that to say that over the years I’ve seen a great deal of technologies come out of Microsoft that resulted in fundamental shifts in the way developers work and what they create. And after 18 years one has a tendency to become a bit ho-hum when new technologies are announced, been there, seen that, done that, kind of attitude. But even with all that history, Silverlight has me excited. Primarily because it carries with it the first glimmers of light at the end of a tunnel of technological promises I’ve been waiting on for many years now: freedom from my hardware. The ability to have extremely rich and compelling applications that run on my desktop, my laptop, my phone, etc… Since my applications can now live in the cloud and be deployed and installed in mere seconds, they are free to follow me around from device to device. We’re not there yet, but it’s easy to see that some of the core scaffolding is starting to fall into place and true freedom is within sight.
Why the Blog?
Well as we move forward into this world of RIA applications that live in the cloud and can follow me around from device to device, there’s going to have to be some change from our old ways of thinking about application development. Just as .NET and C# changed many of our programming paradigms (remember the days when you had to call malloc & free? AddRef() and Release()?), RIAs are going to cause some similar shifts in our thinking. What are those shifts and what are the new paradigms? Well… that’s what I want to talk about here J
Good changes, the kind that last, require exploration, discover, falling down a few rat holes, etc… and that’s what I intend to do here in this blog: Explore, Discover and from time to time go down a rat hole. After 20 years of writing code, I’ve come to grips with del *.*, I’m OK doing that every now and again as long as I learned something in the process.
So I’m going to explore using Silverlight to write a variety of RIA applications, everything from stand-alone utilities, to games and traditional N-tier data applications. As I explore the various programming practices, concepts, patterns, etc… I intend to blog the results here and hopefully that will provide some fuel for discussion.
Beyond the Bling?
What’s with the title of this blog anyway? Well, WPF and Silverlight have enabled us all to build very rich and visually compelling applications. I love this fact because now even graphical neophytes like me can create stuff that looks crisp and nice. But ultimately all that flashy graphics stuff will only get you so far. At some point your boss or your client is going to want a real world functioning application that solves some business need. That application logic/business functionality is the stuff that I refer to as being Beyond the Bling and it’s what I want to focus this blog on. Oh we’ll have bling to be sure, it’s just not the primary focus.