Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Client Side Domain Context Load Manager

0.00/5 (No votes)
21 Apr 2012 1  
Entity Query Load Manager for Entity Framework Domain Contexts.

Introduction

While in the process of working through multiple solutions requiring numerous queries from different, inter-connecting, Domain Contexts, I required a mechanism of knowing when all the queries had completed.

This is mainly because there was no way of doing an include on the servers, because the data was located in physically different databases, and references were added on the client. This made it even more important as Navigation properties were used for binding on the user controls, and as such had to be locked until such time as the data was available.

MultiSyncQueryLoader

MultiSyncQueryLoader is the wrapping class that is responsible for the notification that all the queries were successfully completed. It has been written in a manner that will allow the same mechanism as you would use for a normal query to a Domain Context, but using the AddQuery method instead.

Just so that I give credit where it is due, my colleague Robin Marshall added in the default context and LoadBehaviour properties to allow simplified queries from the Domain Context.

There are two ways of ultimately querying the data using the loader: asynchronous and synchronous (or at least asynchronous but in sequential order).

The RunSync method was designed for the scenario where a callback of one query required that data be loaded by a query, before that callback was actually run.

The RunAsync method will be more typically used by the day-to-day queries that will be run in a Silverlight / Entity Framework environment. This is designed to fire all the queries simultaneously to the relevant services, and await the responses.

Each of the queries will notify via the Completed event when all the queries have finished loading.

DomainContextQuery<T>

The DomainContextQuery<T> generic is where all the magic happens. Its job is to run the EntityQuery against the associated DomainContext and notify the initiator that it has completed.

The Run(Action) method is responsible for running the synchronous calls, as we do not need to pass in a userstate variable for the listening invoker to know what DomainContextQuery was actually being run.

The Run(Action<object>) method, however, is required for the asynchronous calls. This is so that we can extend the method to use the DomainContextQuery that invoked it, should it be required.

Each method will mark the DomainContextQuery as Complete so that it is quick for the MultiSyncQueryLoader to check if there are any outstanding queries, and if not, fire the Completed event.

Using the Code

To explain the use of the code, I will use an excerpt from the attached demo solution:

MultiSyncQueryLoader loader = new MultiSyncQueryLoader(context, LoadBehavior.MergeIntoCurrent);
loader.AddQuery(context.GetCustomersQuery(), (callback) => CustomersLoaded = true);
loader.AddQuery(context.GetCategoriesQuery(), (callback) => CategoriesLoaded = true);
loader.AddQuery(context.GetCustomerDemographicsQuery(), (callback) => CustomerDemographicsLoaded = true);
loader.Completed += () => CompleteLoaded = true;

// Run the queries in any order
loader.RunAsync();

// Run the queries in the defined order above
// loader.RunSync();

To utilise the code, just create an instance of the query loader (use a default domain context and load behaviour if required). Add each query using the method. The AddQuery method has been designed in a way that will not interfere with the original code.

For example, before the query loader, a load from a Domain Context could have appeared as follows:

context.Load(context.GetCustomersQuery(), LoadBehavior.MergeIntoCurrent, callback => { }, null) 

Whereas now with the AddQuery method (and no default context specified):

loader.AddQuery(context,context.GetCustomersQuery(), LoadBehavior.MergeIntoCurrent, callback => { } , null);

Continued Development

Any future development on this project will be maintained on Github. I will always attempt to place an up-to-date version on the article, but its always best to check.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here