Welcome to MSDN Blogs Sign in | Join | Help

Scott McCraw's Blog

These postings are provided "AS IS" with no warranties, and confer no rights.

Syndication

A .NET RIA Services Data Load Batch Manager

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)!

by smccraw | 0 Comments

A Few New Noteworthy SL Samples

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

by smccraw | 1 Comments

Framework Design Studio Released

One of my co-workers, Krzysztof Cwalina has been working on a tool that makes detecting the changes between two versions of an assembly a lot easier.  It's easy to use interface lets you:

  • List the APIs exposed on your public surface area
  • Compares changes in that API across versions of your assembly
  • Markup, comment and review the APIs
  • Export those comments into a Word Document

 

Here's a screen shot from Krzysztof's blog post announcing the release:

FDS

by smccraw | 1 Comments

More Calculator

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 :)
    • sketchy

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:

separation

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! :)

by smccraw | 2 Comments

A Silverlight Calculator

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

Default Calculator Skin

 

A quick overview of the things I explored during this process.

  • The wonderful world of styling controls in Silverlight.  Have a gander at BasicBlack.cs and generic.xaml to see how I set up the styling for my basic calculator skin.  CalculatorAddIn/GlassSkin.xaml shows an example of a new skin over the basic template.
    Glass Style
  • Skinning is also supported, you can rip the entire UI off the calculator and replace it with your own as shown in CalculatorAddIn/SimpleConsole.xaml & .cs.  To support this skinning approach I had to achieve a simple View/Model separation in the code through the use of interfaces (see ICalculatorEngine.cs, ICalculatorCommand.cs and INumericStack.cs).
    Simple Console Skin
  • Support for custom AddIns.  I wanted to let folks write their own calculator functions in addition to creating their own skins.  Checkout App.xaml.cs and CalculatorFrame.xaml.cs for all the code behind loading assemblies on the fly using AssemblyPart.Load().  You can try this on your machine by downloading the ZIP file for the code and selecting the CalculatorAddIn/ClientBin/CalculatorAddIn.dll when the Open Add In dialog opens.
  • IsolatedStorage – interesting concept for remembering what AddIns have been loaded when you come back to the web page.  IsolatedStorageFile.TryIncreaseQuotaTo() is an interesting API to say the least!

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?

by smccraw | 7 Comments

Mix 08 Sessions

I've slowly been working my way through watching all of the recorded Mix sessions.  They are all great and informative, but most folks (myself included unfortunately) don't usually have 100+ hours to sit and watch them all.  So I thought I'd keep a list going of the ones that I have found particularly useful when it comes to creating Silverlight RIA applications.

by smccraw | 0 Comments

Filed under: , ,

<TextBlock Text="Hello World" />

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.

by smccraw | 3 Comments

Filed under: ,

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement  
Page view tracker