Demystifying The Code

EF 4 – Implementing Lazy Loading For My POCO

In my last post, I provided a simple end-to-end example where I used the Entity Framework designer to generate an Entity Data Model (EDM), I turned off the default code generation and implemented my own POCOs.  Everything worked fine, but at the end of the post I pointed out that I no longer had the Lazy Loading capability I had with the designer generated objects.

 

Get the Sample Code

 You can download the sample code here.

 

Lazy Loading for POCOs

At this point, I have a few POCOs which, by their nature, are very simple classes, as well as my context object.  See the Customer class below:

public class Customer
{
    public string CustomerID { get; set; }
    public string CompanyName { get; set; }

    List<Order> orders = new List<Order>();

    public List<Order> Orders
    {
        get
        {
            return orders;
        }
        set
        {
            orders = value;
        }
    }
}

The behavior that I am looking for is: if the Orders for a Customer are accessed and they haven’t been loaded (don’t exist in the context) yet, a call is automatically made to load the Orders for that Customer.  Were you implementing this lazy loading functionality yourself, you might imagine adding some code to the getter for Orders.  This code would check to see if the Orders were loaded and, if not, make a call to load them.

That would certainly work, but your class would no longer be a POCO, would it?  You would have likely imposed some sort of dependency on the framework or at least implemented some data access logic.  What you really want is the framework to provide the lazy loading feature set, while maintaining *no* dependencies on any framework from your POCOs.

 

Lazy Loading Via Dynamically Generated Proxy

So, we have reached a bit of an impasse.  We want to call our lazy loading logic from our getter in our POCO, but by doing that, we would have bound it to the framework and have turned our POCO into a DOOF (Dependant On Other Framework – yeah, I just made that up).  This is where dynamically generated proxies come in.  If you opt in, the framework will dynamically generate a type that derives from your POCO type.  This derived type can override certain properties and “inject” new functionality like lazy loading.

In POCO Proxies Part 1 on the ADO.NET Team Blog, they illustrated a simple example of how lazy loading functionality could be injected.  Below is a screenshot from that example.  Notice that the Orders property is overridden and that a call to the lazy loading functionality (DoLazyLoading() in this simple example) was injected.

image

 

Implementing Lazy Loading for your POCOs

Most of the steps required for implementing lazy loading for your POCO via dynamically generated proxy should be pretty straight forward from the above.  However for clarity sake, I want to be pretty explicit on what you need to do to enable this behavior:

  1. Ensure proxy creation is on.  The context.ContextOptions.ProxyCreationEnabled property must be true.  It is true by default.
  2. Lazy loading must be enabled.  The context.ContextOptions.LazyLoadingEnabled property myst be true.  You can set this in the default constructor of your context object.  Notice the constructor in my context object below.  I set LazyLoadingEnabled to true, as well as explicitly turned on ProxyCreationEnabled explicitly.

    public NorthwindContext() : base("name=NorthwindContext")
    {
        this.ContextOptions.ProxyCreationEnabled = true;
        this.ContextOptions.LazyLoadingEnabled = true;
    }

  3. You have to be able to implement your POCO in a dynamically generated assembly.  Make sure your class is not sealed and is marked public.
  4. Declare any navigation properties that you want to implement lazy loading with as virtual.  See the code below for my customer object.  I have marked the Orders navigation property as virtual.

    namespace NorthwindModel
    {
        public class Customer
        {
            public string CustomerID { get; set; }
            public string CompanyName { get; set; }
    
            List<Order> orders = new List<Order>();
    
            public virtual List<Order> Orders
            {
                get
                {
                    return orders;
                }
                set
                {
                    orders = value;
                }
            }
        }
    }

That is it.  You can now run the sample application and you automatically get lazy loading functionality.  Let’s have a look.  As you can see below, the objects were, in fact, loaded.

image

Having a look at sql profiler, you can see that 4 queries in all were run.  The first was the query to return all of the customers (3).  Tthe next 3 were called via lazy loading.

image

Each time we accessed the Orders from a customer, the lazy loading functionality was called.

image 

(see this post for a discussion of when to use eager vs. lazy loading)

 

Reference Properties Benefit From Lazy Loading, As Well

Lest you assume that lazy loading is just for collections, it works for reference properties, as well.  To illustrate, I have added an Orders ObjectSet to my NorthwindContext:

public class NorthwindContext : ObjectContext
{
    …
    public ObjectSet<Order> Orders
    {
        get
        {
            if (orders == null)
            {
                orders = base.CreateObjectSet<Order>();
            }
            return orders;
        }
    }

    private ObjectSet<Order> orders;
}

I then changed the code in Program.cs to target my new Orders ObjectSet:

using (NorthwindContext nw = new NorthwindContext())
{
    var query = from o in nw.Orders
                where (o.OrderID == 10682 ||
                       o.OrderID == 10856 ||
                       o.OrderID == 10355)
                select o;

    foreach (Order order in query)
    {
        Console.WriteLine("ID:       {0}", order.OrderID);
        Console.WriteLine("Date:     {0}", order.OrderDate.ToString());
        if (order.Customer != null)
            Console.WriteLine("Customer: {0}", order.Customer.CompanyName);
        Console.WriteLine("");
    }
}

Running this code, you will see the following output:

image

By simply marking the Customer property in my Order POCO as virtual, I will get lazy loading:

namespace NorthwindModel
{
    public class Order
    {
        public int OrderID { get; set; }
        public string CustomerID { get; set; }
        public DateTime OrderDate { get; set; }

        public virtual Customer Customer { get; set; }
    }
}

image

Taking a look at sql profiler, you will see that additional queries were run to return customer information that was not already loaded in the context.  Notice that only 2 queries were run via lazy loading.  This is because the customer for order id 10682 is the same as the customer for order id 10856.  It only had to be loaded into the context once.

image

 

Summary

The Entity Framework provides powerful lazy loading functionality for POCOs, while maintaining their integrity.  If you are interested in a more in-depth discussion of this functionality, I would suggest having a look at the following post: http://blogs.msdn.com/adonet/archive/2009/12/22/poco-proxies-part-1.aspx

EF 4 – Implementing POCO Objects

The EF team has released the POCO template for use with VSTS 2010 Beta 2.  I thought I might examine POCO support in the new version of the Entity Framework without taking advantage of the template first, then get into the template in a later post.  This post will provide a simple end-to-end sample of implementing POCO objects in EF4 (Beta 2).  If you are reading this, you probably already know that POCO refers to “Plain Old CLR Objects”.  These are simple objects that are free of any framework dependencies.  POCO objects do not have to inherit from specific classes, do not have to implement specific interfaces, nor do they require any specific attributes.  They are simple, lightweight objects that are used to pass data around.

The Entity Framework 4 provides support for POCOs.  This post will illustrate this using a simple example from Northwind, a database that everyone has access to.  Feel free to follow along.  All you need is the following:

The SQL Data Model

image

Above you will see a small part of the SQL Data Model for Northwind.  These are the 2 tables that I am going to use.  In fact, for simplicity sake, I am not going to return each column from the 2 tables.  I have highlighted the columns that I plan on using.  With that out of the way, let’s get started:

 

Implementing this Simple Model without POCO

I will get started implementing this simple model without POCO.  Here goes:

  1. Open Visual Studio 2010 Beta 2
  2. Create a new Console Application
    • Click File > New > Project
    • Choose Console Application – For me it is under:  C# > Windows
    • Give It any name you want.  I’ll name mine SimplePOCO

    image

  3. Add the ADO/.NET Entity Data Model:
    • Click Add > New Item > ADO.NET Entity Data Model
    • Name It: NorthwindModel
      image
    • Click ‘Add’
    • Choose ‘Generate From Database’ and click ‘Next’
      image
    • Choose a connection to the Northwind database
      • (If you have not created a connection, you will need to click ‘New Connection’ and add a connection to Northwind.asdf
      • Save the entity connection settings in App.Config as ‘NorthwindContext’ 
        image 
      • Click Next
    • Choose the tables and set the Model Namespace
      • Choose the Customers and Orders Tables
      • Set the Model Namespace to NorthwindModel.  This is an important decision.  As you might infer, this will act as the namespace for your entire conceptual schema.  In other words, if you generate objects to represent your entities, they will have the NorthwindModel CLR namespace.  If you choose to create POCO objects, you will have to namespace them with NorthwindModel.
      • Click ‘Finish’
        image
  4. Delete the unneeded properties from our conceptual model. Remember that earlier I highlighted the columns in the database model that I wanted to use. We need to delete the properties from our conceptual model that map to the unneeded columns.
    • Simply single click on the unneeded columns (see image below) and click delete
    • You can multi-select columns

    image 

     

  5. Write some code in Program.cs to test the model:
    • Open Program.cs
    • Type the following code under Static Void Main

      static void Main(string[] args)
      {
          using (NorthwindContext nw = new NorthwindContext())
          {
              var query = from c in nw.Customers
                          where c.CompanyName.StartsWith("A")
                          select c;
      
              foreach (Customer c in query)
              {
                  Console.WriteLine("{0}", c.CompanyName);
      
                  foreach (Order order in c.Orders)
                  {
                      Console.WriteLine("\t{0}", order.OrderDate.ToString());
                  }
              }
      
              Console.ReadLine();
          }
      
      }

  6. Run It! You will see that not only does our model work, but we got lazy loading for free (I’ll get into Lazy Loading in another blog post.)

    image

That is it for implementing the model without POCO.  To illustrate that the object that were generated by the EF are not POCO, simply open the NorthwindModel.Designer.cs file.  This contains all of the designer-generated code.  

image

You need only take a brief look at the Customer or Order class to see that they have both EF attributes, as well as implement classes from the framework:

image

 

What Have We Got So Far?

Before I move on to the POCO side of things, I think it is probably best to describe a bit more about what has been done so far.  To start with, we used a wizard to generate an Entity Data Model (EDM) from our database schema.  If you are not familiar with what an EDM is, it contains a schema to the physical store (database), a schema for our conceptual model (how we want to see the data in our application) and a mapping between the two.  If you open the *.edmx file with an XML Editor (Right-Click NorthwindModel.edmx > Open With > XML Editor, you will see that, aside from the designer markup, the edmx is just that.

image

The second relevant thing that happened was that the designer generated some classes for us that map to the entities defined in the conceptual side of the EDM (using a template against the EDM).  You can see these classes if you open up the NorthwindModel.Designer.cs file.  These are the classes that will be used if you go through Object Services.  If you are not familiar with Object Services, you can think of it this way:  if you think of the Entity Framework as an ORM, Object Services provides the O.  In other words, if your query (LINQ to Entities or Entity SQL) returns objects, you are going through Object Services.  As seen in the step-by-step guide above, the classes are far from POCO.  There are multiple dependencies on the Entity Framework in the form of both attributes and inheritance.

 

Implementing the POCO Objects

In order to implement POCO Object, we first need to turn off the code generation that occurs by default.  Next, we create our POCO Objects.  Here are the steps:

  1. Set the Code Generation Strategy to "None"
    • Make sure the properties pane is visible
    • Click on whitespace in the edmx designer
    • In the properties window, set Code Generation Strategy to "None"

    image

  2. Add the Customer Class to the project
    • Right-Click the project > Add > Class
    • Name it Customer.cs
    • Change the namespace to NorthwindModel (Remember earlier that we set the model namespace to this)
    • Implement the Customer class so it looks like the following (excluding using statements)

      namespace NorthwindModel
      {
          public class Customer
          {
              public string CustomerID { get; set; }
              public string CompanyName { get; set; }
      
              List<Order> orders = new List<Order>();
      
              public List<Order> Orders
              {
                  get
                  {
                      return orders;
                  }
                  set
                  {
                      orders = value;
                  }
              }
          }
      }

  3. Add the Order Class to the project
    • Right-Click the project > Add > Class
    • Name it Order.cs
    • Change the namespace to NorthwindModel (Remember earlier that we set the model namespace to this)
    • Implement the Order class so it looks like the following (excluding using statements)

      namespace NorthwindModel
      {
          public class Order
          {
              public int OrderID { get; set; }
              public string CustomerID { get; set; }
              public DateTime OrderDate { get; set; }
      
              public Customer Customer { get; set; }
          }
      }

  4. We now need to add the context class. This is a class that inherits from ObjectContext and acts as the gateway or into your objects. You go through this context to access your entities as objects.
    • Right-Click the project > Add > Class
    • Name it NorthwindContext.cs
    • Change the namespace to NorthwindModel
    • Implement the NorthwindContext class so it looks like the following

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Data.Objects;
      
      namespace NorthwindModel
      {
          public class NorthwindContext : ObjectContext
          {
              public NorthwindContext() : base("name=NorthwindContext"){}
      
              public ObjectSet<Customer> Customers
              {
                  get
                  {
                      if (customers == null)
                      {
                          customers = base.CreateObjectSet<Customer>();   //"NorthwindContext.Customers");
                      }
                      return customers;
                  }
              }
      
              private ObjectSet<Customer> customers;
          }
      }

  5. Add a using statement to Program.cs for NorthwindModel:

    using NorthwindModel;

  6. Run It!

    image 

Summary

In this simple tutorial, we created an Entity Data Model, swapped out the objects that are generated by the designer for some custom POCOs that we created and wrote our own context object to expose our new object layer.  At the very end, our example worked, but we did not get some of the services that the designer-generated objects provided.  Most obviously, we did not get lazy loading.  I will put together a post for Monday that will illustrate how easy it is to implement that.  Oh yeah, and I’ll show off the new POCO template next week, as well.

Is Lazy Loading in EF 4 Evil or the Second Coming?

(As you probably know) The Entity Framework provides you with various options for loading related entities.  In Entity Framework 4, you will have the choice to implement eager loading, explicit loading and now… lazy loading.  Lazy loading was not available in version 1.  A quick search on ‘Lazy Loading’ will yield opinions from 2 very different camps.  Some folks see lazy loading as a necessity for an ORM, while others believe it to be evil.  So, who is right?  This post will examine that question.  If you are not familiar with all of the load options are, I will start the post with a brief description of each.

 

The Code Scenario

We will use the following simple scenario to examine the various load options.  In this scenario, we have 2 entities that we are surfacing as objects: Customer and Order.  Each customer has 0 to many orders.  Imagine the following code accessing the customer and it’s orders (in this case in a console application):

using (NorthwindContext nw = new NorthwindContext())
{
    var query = from c in nw.Customers
                where c.CompanyName.StartsWith("A")
                select c;

    foreach (Customer c in query)
    {
        Console.WriteLine("{0}", c.CompanyName);

        foreach (Order order in c.Orders)
        {
            Console.WriteLine("\t{0}", order.OrderDate.ToString());
        }
    }

    Console.ReadLine();
}

For the sake of this example, assume that we have 3 customers, with a total of 24 orders between them.

Eager Loading

With eager loading, you structure the initial query in such a way that all of the required objects are returned in the initial query.  If you are a SQL person, you can think of this as building a join query.  In fact, if you are using the SQLClient Provider, that is exactly what eventually gets executed against SQL Server. 

How Do I Do Eager Loading?

You implement eager loading in LINQ to Entities with the ‘Include’ method.  An include specifies the related objects to include in the query results.  So, given the previous example, we would re-structure the original query to look like this:

var query = from c in nw.Customers.Include("Orders")
            where c.CompanyName.StartsWith("A")
            select c;

The Result

Taking a look at the screenshot of SQL Profiler, you will note that in order to return the 3 customers and the 24 associated orders, only 1 query was executed.  You can also see the join to the Orders table in the SQL statement that was executed.

image

Discussion

So is eager loading good?  Is it bad?  It depends upon the scenario.  On a positive note, only 1 query had to be executed.  This means that we only  needed one connection and incurred the overhead of making one network round trip.  On the other hand, every order was returned, resulting in a potentially large resultset. and the initial query included a join which is more expensive than a query against a single table, 

In a scenario where a high percentage of the related objects are traversed, eager loading would be a great choice.  In a scenario where the object graph can be quite large and you sparingly traverse the related objects, it may be a poor choice.

 

Explicit Loading

With explicit loading, you explicitly request to load the related objects.  In essence, you run an original query to return an object or collection of objects.  When you want to process the related objects for that object (or an object in the collection), you explicitly request to have the related objects returned.

How Do I Do Explicit Loading?

You implement explicit loading by calling the Load method on an EntityCollection or EntityReference.  So, given the previous example, we would re-structure the code to look like this:

using (NorthwindContext nw = new NorthwindContext())
{
    var query = from c in nw.Customers
                where c.CompanyName.StartsWith("A")
                select c;

    foreach (Customer c in query)
    {
        Console.WriteLine("{0}", c.CompanyName);

        c.Orders.Load();
        foreach (Order order in c.Orders)
        {
            Console.WriteLine("\t{0}", order.OrderDate.ToString());
        }
    }

    Console.ReadLine();
}

Notice that I removed the call to Include.  Further note that prior to iterating over the Orders collection, I am explicitly calling Load.

The Result

From the profiler screenshot below, you will notice that 4 queries were run in total.  The first query returned just the customer information.  Then, I explicitly called ‘Load’ prior to enumerating over the orders for each customer.  Each call to load made a separate call to the database with all of the associated overhead: a connection, network round trip, etc.

image

Discussion

As with eager loading, explicit loading can be performant or not depending upon the scenario.  Again, given the scenario where a high percentage of the related objects are traversed, eager loading would likely be a better choice.  However in the second scenario where the object graph can be quite large and you sparingly traverse the related objects, explicit loading may be a better choice.

 

Lazy Loading

With lazy loading, related objects are loaded automatically for you when you access them.  You can think of it like explicit loading, but the call to Load is called for you automatically when you access the object in question.  To be clear, the query is only run if the objects are not already in the ObjectContext. 

How Do I Implement Lazy Loading?

If you are using the Entity Framework designer with the default code generation strategy, you are already set up for lazy loading.  The default value of LazyLoadingEnabled for a context is false,  However, the default code generation template sets the ContextOptions.LazyLoadingEnabled property to true in each of the constructors for the context – see screenshot below.  (You can easily implement lazy loading for POCOs, as well.  I’ll illustrate how to do that in a post next week.)

image

Given that lazy loading is set up, you do not need to do anything else (that is the lazy part).  You simply access the objects in question.  If the objects are not already in the context and you have not eagerly loaded them with an Include and you have not explicitly loaded them with Load, they will be loaded for you automatically.  With lazy loading enabled, the code listed under ‘The Code Scenario’ at the top of this post will work as-is.

The Result

The result is the same as the example of explicit loading.  In our simple example, 4 queries were run in all.

Discussion

The issue of relative performance is the same as explicit loading. 

 

The History of Lazy Loading and the Entity Framework

As mentioned at the beginning of this post, lazy loading was not available in the first version of the Entity Framework.  The mindset was that, with lazy loading, it was possible for someone to unknowingly make network calls.  As these calls are expensive, this was viewed as bad.  The decision was made to force people to be explicit when making a network call. 

This decision was not well received by everyone and not without it’s issues.  Take a look at the following excerpt from the now infamous ADO .NET Entity Framework Vote of No Confidence:

image

The reality was that virtually every ORM on the market supports lazy loading.  The excerpt relayed that without this functionality, the developer is required write unnecessary code to get the expected results.  Take the code laid out in ‘The Code Scenario’ at the top of this document.  Without lazy loading, the results of this code are shown below:

image

That is not an accurate depiction of the data.  To the untrained eye, it appears that each customer has no orders – a bit of a false negative.  In v1, the developer would have been required to add the code to see if the orders were loaded and if not, call Load. 

 

Is Lazy Loading Evil or the Second Coming?

It should be mentioned at the outset that the existence of lazy loading (or explicit loading for that matter) does not preclude you from using eager loading in scenarios where that makes sense.  Another point to make is that after all is said and done, explicit loading and lazy loading offer the exact same performance benefits and challenges.  What this means to me is that if you have implemented explicit loading in the appropriate places, lazy loading is not evil at all.  It will behave exactly as though you had made the correct explicit calls.

If you buy into that logic, the remaining issue is with code where eager loading was not implemented appropriately.  Antagonists for lazy loading would argue that, in this case, the uninformed developer would be making unnecessary calls to the database without any knowledge (assuming that they never profile their code).  Protagonists of lazy loading might mention that a) one should profile one’s code and b) in order to make the code work without lazy loading is to write a bunch of unnecessary code to see if the items were loaded and, if not, load them.  They might follow on that if this same uninformed developer failed to write that ancillary code, their solution would be riddled with false negatives.

So, who is right?  Both? Neither?  It is simply a matter of opinion.  There are folks on both sides that will never buy into the contrary viewpoint.  Given that both camps are going to theoretically be consumers of the Entity Framework, it should be clear that lazy loading should be an option.

Now, should it be on by default?  In beta 2, it is kind of on by default and kind of not.  LazyLoadingEnabled is actually defaults to false.  However, if you use the default code generation in the EF, it is set to true in all of the constructors for the context object.  That is the way it is.  The question is: is that ok?

That is actually a tougher question to answer.  IMHO, that was a questionable choice.  I’m actually ok with having LazyLoadingEnabled defaulting to false.  I would have been equally ok with having it default to true.  I would probably lean further toward having it default to true, if pushed.  However, it has to be one or the other and there are valid reasons for both.  At some point you have to make a decision and I assume that is what they did.  What I don’t really like is that if you use the default code gen template, it reverses this decision.  I think that once you take a stance on the default, you should remain consistent.  I understand that it is nice to illustrate how to set this property in the generated code.  Perhaps a better decision would have been to (re)set it to false and have a comment pointing out to set it to true.

To conclude, lazy loading is neither evil or the second coming.  It is a necessary feature of any ORM today and I’m glad it is in the EF.

Finding a Nursery School

After our first day of house searching with Claire, it was time to look for a nursery school for Jack.  We again had a representative from our relocation company to help us with this.  For the afternoon, we had meetings set up with 2 schools.  Now, right before Claire dropped us off after our house search, she was “kind” enough to give us a map where she had placed little stickers where all of the area nursery schools were.  Nice, huh?  WRONG.  She misplaced and mislabeled at least 2 of the schools as we were soon to find out.

About a half hour after we were dropped off, it began sprinkling mildly.  We found our way safely to the first Nursery school.  It was situated at the back of a large sports complex.  Within the complex was a nice health club and backing up to the complex was a golf club.  So, of course, as we were walking towards the nursery school, we were having daydreams of getting in a round before school or getting in a quick workout right after.  That was before we entered the nursery school / frat house. 

We were right on time for our scheduled appointment and were shown directly in.  We were asked to take off our shoes at the door.  I remember thinking that that was a good sign because they were concerned about the cleanliness.  That thought lasted about 4 nanoseconds – until we walked into the first room.  Honestly, there was crap everywhere.  Garbage was all over the floors, intermixed with the kids.  Creepy toys were everywhere.  The place was filthy.  All the while, our guide was walking us from room to room telling us about the nursery.  I wasn’t listening very hard because it took a lot of effort to not throw up in my mouth. 

It is important to be clear that at no time did I ever consider the possibility of leaving my son there.  What was weird was that I started feeling intensely guilty for even being there.  So it was with massive relief that we left that school and ventured back out into the rain.  We were on foot with no car or umbrella, but it was considerably better than the nursery.  On another positive note, it wasn’t raining that hard and we did have Claire’s map (start eerie music here).

We decided to head out to our second appointment a bit early so we referred to our trusty map.  It looked like about a 15 minute walk, so opted against researching buses, invested in a small umbrella and started our short walk.  It turns out our estimate was spot on.  We got to the area corresponding to the sticker on Claire’s map in just about 15 minutes.  On a slightly less positive note, 2 major issues began to emerge: 1) there was no school in that location and 2) we were now standing in a torrential downpour. 

After 15+ years writing software, I have learned a simple lesson.  More often than not, when I thought there was a bug in a framework component, it was actually a problem with my code.  So when we had a problem with the map, I initially assumed it was really an issue with my interpretation of the map and not the map itself.  So, we walked up and down the street where the school should have been eleventy-billion times looking for anything that looked like a school.  Nothing.

I should probably mention that we had purchased a pay-as-you-go phone earlier in the day.  Being of Scottish descent, I have a frugal streak running through me.  Obviously, we bought the cheapest phone available for  £10.  After 15 minutes looking about in the rain we gave them a call.  What you should be picturing right now is an idiot talking into a can connected to a string because that is about as effective as the phone we bought.  Between the rain and the traffic, we could hear NOTHING. 

At this point, our mini umbrella (again I opted for the cheapest one available) was rendered useless.  We were drenched, disheartened and still lost.  After another half hour of wandering around, we found an open business and got some directions to the school.  It was over a mile up the road.  Consulting our trusty map, we noticed that there was a marker for this new location.  Unfortunately, it was listed as a different school for which we had an appointment on another day.

You can probably imagine how we looked when we finally made it to the school.  We were soaked to the bone.  Unfortunately for Carrie, she was wearing brand new jeans that had been washed at most once.  The result was that her legs were stained blue.  Nice.

The afternoon did end well, though.  The school was great.  We loved the teachers, the classrooms, basically the whole facility.  We had found Jacks new school.  Now all we need was a home.  More later…

Taking the Housing Trip – Finally

We finally got the Visa thing squared away and were finally able to take our housing trip.  The trip was for 4 days in London.  In that time, we were supposed to find a home for us to rent, find our temporary housing and identify a school for our son.  Again, we had the expertise of our relocation company on which to rely.  That is where this part of the story begins…

 

Finding our House

Carrie had already taken a trip to London a few weeks prior and found a great town just outside of London called Richmond.  It is a nice family-oriented spot with shopping, nice restaurants and is on the tube.  With that narrowed down, we just needed to find a place to live.  So we told our representative, we’ll call her Claire, to look there for us.

I’m at a bit of a loss on how to describe Claire, but I’ll give it a go.  Have you ever met someone that thinks they know what’s best for you, regardless of your opinion?  Add to that: 2 parts used car salesman and 3 parts rude French waiter.  Cover it with gray hair, throw on some lipstick, put it in the oven for 30 minutes and you have Claire.

Now, there is something about me that you may not know.  I sold copiers for a year when I was just out of college (I was young; I needed the money).  When you take a job hocking boxes they teach you each and every sales tactic.:  things like the assumptive close, many little yeses lead to a big yes, etc.  Keep that in mind while we describe our encounter with Claire.

 

Meeting Claire

We were pretty excited when we went to meet Claire.  I mean, how many times in your life do you get to find a new home?  So it was with that excitement that we sat down with her for the first time.  Claire began the conversation letting us know that we were a bit late (we were) and we needed to hurry.  This just after she got my wife a coffee. 

Next, she let us know that this was the worst time of year to try to rent a house and that most of the good ones were gone.  In fact there were 2 houses that were “perfect for us” that just rented out last week.  That royally pissed us off because they would have been available to us had our Visas been done on time and we been able to make our original housing trip.

Claire then let us know that she lined up 12 or so houses for us to see.  She relayed that she set up the appointments in order of importance.  In her opinion, we should probably rent the first house as it was best suited for us.  However, in the unlikely event that she was wrong, she had 5 other adequate places for us to see thereafter on day one.  The houses on day 2 were pure rubbish (this is because there is nothing available and had nothing to do with her searches btw).  With that in mind, Claire was kind enough to let us know that, given all of these factors, it was in our best interest to make an offer by the end of day one.  If not, it was likely someone else would make an offer on those properties in short order.

After hearing this, I had some mild, if not severe, flashbacks to copier sales school.  Claire had employed every tactic I learned on day 1.  She had set expectations, as well as established a high degree of urgency.  I wouldn’t have been surprised if she had whipped out a Lanier 6242 (42 copy per minute system I used to sell back in the day), showed me a demo and presented me with a contract.  That was how our day started.

 

Claire’s Top Picks

I do have to say that the first 2 were fine houses she showed us were fine places (we actually rented the 1st, but we’ll get back to that later).  The positives were that they both met our requirement of 4 bedrooms (one for us, Jack, an office and guest room) and were close to the tube (the underground train station).  They also had a bonus in that they each had a garage and driveway with a parking spot (neither very common in the London area). 

The negatives were that both had small reception rooms (we call them family rooms in the US), no fireplaces, small bedrooms and tiny showers.  I don’t have the actual square footage, but I would guess around 1000.  Now, we knew to expect much smaller houses in the London area.  However, these places cost a premium (approximately twice what we could rent our 2800 square foot house in Phoenix for) and for all of that none of our furniture would fit.  Forgetting the cost of buying all new furniture, the showers are small enough that I’m not sure I’ll be able to reach up to clean my arm pits – so don’t sit next to me on the train until it can be confirmed.

We gave Claire all of this feedback and we continued the search.  We then saw the next 5 or so houses scheduled for that day, but none of them were all that great.  We were starting to get concerned because Claire had already warned us that the houses for day 2 stunk, but that was a problem for day 2.  It was only noon and we had a half day of looking at nursery schools ahead of us.  I’ll detail that tomorrow…

Moving to London – The Housing Trip

As some of you might know, my wife was recently offered a great position in London with her company.  At the suggestion of a friend of mine, I have decided to chronicle the experience on this blog.

 

The Process

Moving unto itself is a huge process.  Moving overseas adds a whole laundry list of additional complexities.  To start with, there is the procurement of the Visas.  Secondly, the moving of your stuff is split up into an air shipment which takes 4 weeks or so and a sea shipment which takes a couple of months.  Thirdly, it is pretty costly to travel overseas, so you are generally limited to a single trip prior to moving to find your housing.  Lastly, due to the length of time it takes to ship your furniture, sheets, pots, pans, etc., you can expect to stay in temporary housing for a decent period of time – a month or so.

Now, my wife’s company understands all of this, so they hire a relocation company to help us with all of these details.  This is where our story begins.

 

The Visas 

Attaining our Visas was our first challenge.  In order to help guide us through these unknown waters, our relocation company assigned us a representative knowledgeable of the process.  From the very beginning we told our rep that we had a housing trip planned the third week in November.  The trip was 3+ weeks prior to our move.  We wanted that kind of buffer because we were not sure what size house / flat we would find.  As a result, we did not know whether our furniture would fit or not.  Given a smaller place, we would have to put some furniture in storage, as well as purchase some more appropriately sized furnishings.  Our representative assured us that we would have our Visas in time.

Having a big company sponsor you is a huge help in gaining a Visa.  There are, however, still some obstacles.  For instance, the UK wants to ensure that you are able to pay for housing for at least your first month there.  The means by which they validate this is to ask you to illustrate that you have maintained a minimum balance of something like $3000 in a checking or savings account over the past 6 months. 

I’m not sure how you roll, but we do not maintain a savings account.  Our “extra” money goes into the market in an investment account.  As for our checking account, we do maintain an average balance of over $3000.  However, we do not maintain a minimum balance of $3K.  It has fallen well below this floor.  Truth be told, It has actually fallen below 0.  Although we assured our representative of these unfortunate truths, she insisted that we burn thousands of calories gathering this documentation for her.  We were able to put together the requested documentation after 10 days or so (we had to request official copies from the bank because we get our statements online) and forwarded them on to her.  She crunched all of our information against her years of experience and her professional opinion was – wait for it – we had not maintained a balance of at least $3000.  She is good!

I hope I didn’t misrepresent the situation.  Reading the above you might have come to some wrong conclusions.  Specifically, you might have assumed that, upon receiving the documents, coupled with our verbal assurance, it was instantly clear to our seasoned representative that we did not meet the criteria.  That was not the case, as we heard nothing for days.  We began pinging our rep, wondering what our recourse was, only to get out-of-office replies.  Apparently, our financial position caused enough stress to require a brief vacation.

Upon her return, we found out that our only recourse was to request a document from my wife’s company guaranteeing payment of our housing for the first month.  We thought that this was a no-brainer.  As part of my wife’s package, her company was putting us up in temporary housing for – you guessed it – a month.  Silly, silly me.  Gaining this seemingly simple guarantee took close to a month (I can’t remember exactly, but I think there may have been a small vacation in there too).

The net-net was that, despite constant assurance that we would have our Visas in time for our housing trip, they were a few days late.  As a result, we had to push back our move date a few days and reschedule our housing trip to a few days before our move.  I’ll get into that more in coming posts…

Uncle Fergal Helps Us Pronounce Azure

On the advent of PDC 09, I wanted to pass along one of my key learnings since PDC 08.  As you probably know, it was at PDC 08 where Microsoft introduced our cloud platform Azure.  From that day on, there has been mass confusion as to the pronunciation of Azure and the issue quickly reached pandemic proportions.  I’ve personally witnessed everything from az-yoor to ah-zher to as-sure.  I would have been willing to simply ignore the verbal missteps had it not been for a sign…  literally a sign…

churchsign1

I racked my brains for days following my encounter with that sign.  Who or what is a Fergal?  It was perplexing.  The only thing I could think of was that I have an Uncle Fergal in Scotland.  Maybe the sign wanted me to contact my Uncle Fergal, ask him how to pronounce Azure and to spread the word.  Well, as they say, when in Scotland …  The following is part of my conversation with Uncle Fergal.

Install Microsoft Silverlight

FergalLarge(Uncle Fergal)

Patterns-Based Silverlight Development – Part IV – Service Layer

In this post, I will be building the WCF Services layer that my client layer will call.  I will be using the custom binding made available with Silverlight 3 that enables a decreased message size through encoding the message as binary rather than text.  I will also write some code to test this layer.

 

Adding the WCF Service

Add the web

Before I can add the WCF service that my Silverlight component will consume, I need to add the Web application to my solution.

  1. Right-Click the Server solution folder –> Add –> New Project
  2. Under Visual C# –> Choose ‘Web’ –> ASP.NET Web Application
  3. Name it HelpDesk.Web
  4. Delete Default.aspx

Add the service

In Silverlight 3, we re-implemented the ‘Silverlight-enabled WCF Service’ template.  In Silverlight 2, the template wired up the basicHttpBinding.  If you know your WCF, you know that this is the ‘Interoperable Binding’, conforming to the WS-I Basic Profile 1.1.  In Silverlight 3, it wires up a custom binding

  1. Right-Click HelpDesk.Web –> Choose ‘Add’ –> New Item
  2. Under Visual C# –> Choose ‘Silverlight’ –> ‘Silverlight-enabled WCF Service’
  3. Name it TicketService.svc
    image
  4. Add a project reference to HelpDesk.Data.  We will need that.

Out-of-the-box Configuration

Let’s take a look and see what  the ‘Silverlight-enabled WCF Service’ template gives us out-of-the-box.  See below:

image

You will notice that the bindingConfiguration points to a customBinding.  This binding configures a binary message encoder that encodes Silverlight messages in binary on the wire.  This binary format is compatible with the Windows Communication Foundation (WCF) binary message encoder.  This will result in decreased message sizes.  The caveat is that you should revert back to basicHttpBinding if you have non-.NET clients, as this binary format is WCF-specific.

As I stated, this is the out-of-the box configuration.  We will need to make some additions in order to allow us to propagate our exceptions to the client.  We’ll take a look at that now.

 

Handling errors with FaultException<T>

I tend to think of exceptions falling into a couple of categories:  1) Business exceptions – exceptions that the user caused and can resolve.  Breaking validation rules falls under this category.  2) Technical Exceptions – exceptions that the user did not cause.  An example would be that the database is down.  3) Security Exceptions.  In our application, we need a way to pass all kinds of exceptions to our Silverlight client.  Further, in the event of a validation exception, we need to let the client know which rules were broken.

This was a bit of a challenge prior to Silverlight 3.  Now, with some work, we can pass exceptions from our services layer to our Silverlight client with FaultException<T>.  Why did I write “with some work”?  Well, it is important to understand that Silverlight 3 defaults to using the browsers networking stack for HTTP calls (you can opt in to using another networking layer called the client networking stack).  By default, a FaultException will be sent to the client with a 500 HTTP status code.  What this means to you is that Silverlight will not be able to access the bodies of these messages.  What the client will see is a 404 NOT FOUND.

In order to make this work, we need to configure the WCF service to set the status code to 200 (OK).  Don’t worry, it will still be seen as an exception on the client.  We will see that in a moment.  First, let’s get it set up.

Creating our Silverlight.Patterns Project

Until now, I have been adding some generally re-usable classes to my HelpDesk.Data project and that is just wrong.  I am going to add a project that will contain classes that I will be able to re-use over and over again… classes like the RuleViolation or my ValidationException.  (I should note that I did have to decorate my RuleViolation class in order to make it serializable).  I will also add another class or two here.  First, I am going to add the project, move these 2 classes over, change their namespaces and set the appropriate references.  I am not going to detail all of that work in this post, as it is grunt work.  Please feel free to download the code from this session and you will see the changes reflected there.  One last thing, before I move on…  I stink at naming assemblies, so if you have any suggestions for a better name than Silverlight.Patterns, please lay a comment on my blog.  I am all ears.  For now, I will be adding these classes to that project and will use Silverlight.Patterns as the root namespace.

Adding a the SilverlightFaultBehavior class

As outlined in the online documentation article Creating and Handling Faults in Silverlight, we are going to create a WCF endpoint behavior that will set the HTTP status code to 200 for Silverlight FaultExceptions.  I will create this behavior in my new Silverlight.Patterns project.  Now, I am copying the code directly from the link above, so I am not going to show it all in this post.  You are free to download the code for this article and see it, though.  I will show the important pieces here. 

namespace Silverlight.Patterns.Faults
{
    public class SilverlightFaultBehavior : BehaviorExtensionElement,
        IEndpointBehavior
    {

        public override Type BehaviorType
        {
            get { return typeof(SilverlightFaultBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new SilverlightFaultBehavior();
        }
        ...

You can see above that we created a class called SilverlightFaultBehavior that implements BehaviorExtensionElement and IEndpointBehavior.  Below you will see the ApplyDispatchBehavior member from IEndpointBehavior.

public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
    EndpointDispatcher endpointDispatcher)
{
    SilverlightFaultMessageInspector inspector =
        new SilverlightFaultMessageInspector();
    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}

As you can see in ApplyDispatchBehavior, it creates an instance of a type called SilverlightFaultMessageInspector (we’ll see that in a moment) and adds it to the MessageInspectors class of the dispatch runtime.  That inspector is doing the work of setting the status code to 200.  Take a look:

public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
    public object AfterReceiveRequest(ref Message request,
        IClientChannel channel, InstanceContext instanceContext)
    {
        return null;
    }

    public void BeforeSendReply(ref Message reply,
        object correlationState)
    {
        if (reply.IsFault)
        {
            HttpResponseMessageProperty property =
                new HttpResponseMessageProperty();
            property.StatusCode = System.Net.HttpStatusCode.OK;
            reply.Properties[HttpResponseMessageProperty.Name] = property;
        }
    }
}

If the reply is a fault, the status code is set to 200 (OK).  This will allow Silverlight 3 to see the fault.

Configuring the Service for the SilverlightFaultBehavior endpoint behavior

We need to update the web.config for our service to add this endpoint behavior.  Here is what we need to do:

  1. Add the extension (directly under System.ServiceModel)

    image
  2. Add the endpoint behavior (just below the serviceBehaviors node)

    image
  3. Add the behaviorConfiguration to the endpoint

    image

We are fully configured now.  When a FaultException is thrown, it will be sent across with a status code of 200.

Adding the FaultDetail

Remembering back, we want to enable sending a FaultException<T>.  What is the ‘T’ part?  We want to pass to the caller some information about the exception.  What I have chosen to send across in this sample is a Message, a “Type” and the RuleViolations collection. 

The “Type” will be a string that the client can use to determine what kind of exception it was.  ValidationExceptions will have a type of “ValidationException”, whereas, uncontrollable exceptions will be “TechnicalException”.  The RuleViolations collection will return all of the validation violations. Finally, the Message should be client-friendly (you should assume that the message will be directly exposed to the user.

namespace Silverlight.Patterns.Faults
{
    [DataContract]
    public class FaultDetail
    {
        [DataMember]
        public string Message { get; set; }

        [DataMember]
        public String Type { get; set; }

        [DataMember]
        public List<RuleViolation> RuleViolations { get; set; }
    }
}

 

Coding up the Service

Setting up the repository

I have my service configured the way I want it (set up to take advantage of binary encoding and FaultException<T>), so now I need to start writing the implementation.  We will start by introducing the concept of our repository to the service, and to provide a hook where we can adequately test the service operations without calling over http. 

The template stubs out a simple service operation called DoWork. We will delete that.  The next thing we want to do is to add a field for our ITicketRepository.  Next, I want to add a couple of constructors.  I want an overloaded constructor where I can pass in an ITicketRepository instance.  This will provide me a hook where I can pass in a FakeRepository for testing purposes.  I also want to implement the parameterless constructor that WCF will call.  This will set up the real repository for us.  See the code below:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TicketService
{
    ITicketRepository repository;

    public TicketService()
        : this(new TicketRepository())
    {

    }

    public TicketService(ITicketRepository theRepository)
    {
        repository = theRepository;
    }
}

Our test code can now call the overloaded constructor, passing in the Fake Repository.  Now we can move on to writing the operations.

Implementing the Fetch Operations

The fetch operations are pretty simple (because we have already implemented the repository and the pipeline.  Here they are:

[OperationContract()]
[FaultContract(typeof(FaultDetail))]
public List<Ticket> GetAllTickets()
{
    try
    {
        List<Ticket> tickets = repository.GetTickets().ToList();
        return tickets;
    }
    catch
    {
        FaultDetail detail = new FaultDetail();
        detail.Message = "An error occured returning the tickets";
        detail.Type = "TechnicalException";
        throw new FaultException<FaultDetail>(detail);
    }
}

[OperationContract()]
[FaultContract(typeof(FaultDetail))]
public List<Ticket> GetTicketPage(int pageNumber, int pageSize)
{
    try
    {
        List<Ticket> tickets = repository.GetTickets().ByPage(pageNumber, pageSize).ToList();
        return tickets;
    }
    catch
    {
        FaultDetail detail = new FaultDetail();
        detail.Message = "An error occured returning the tickets";
        detail.Type = "TechnicalException";
        throw new FaultException<FaultDetail>(detail);
    }
}

[OperationContract()]
[FaultContract(typeof(FaultDetail))]
public Ticket GetTicket(int ticketID)
{
    try
    {
        return repository.GetTickets().ByTicketID(ticketID);
    }
    catch
    {
        FaultDetail detail = new FaultDetail();
        detail.Message = "An error occured returning the ticket: " + ticketID.ToString();
        detail.Type = "TechnicalException";
        throw new FaultException<FaultDetail>(detail);
    }
}

[OperationContract()]
[FaultContract(typeof(FaultDetail))]
public List<SeverityLevel> GetAllSeverityLevels()
{
    try
    {
        return repository.GetSeverityLevels().ToList();
    }
    catch
    {
        FaultDetail detail = new FaultDetail();
        detail.Message = "An error occured returning the severity levels";
        detail.Type = "TechnicalException";
        throw new FaultException<FaultDetail>(detail);
    }
}

As you can see, in the event of an exception, we throw a FaultException, providing a FaultDetail.  In that FaultDetail, I am setting a client-friendly message, along with a Type of “TechnicalException”.  Notice that I have decorated each operation with a FaultContract, passing the type that will pass our error information back to the caller.

Implementing the Update Operation

The update operation is a bit more interesting.  Here is the code:

[OperationContract()]
[FaultContract(typeof(FaultDetail))]
public void UpdateTicket(Ticket ticket)
{
    Ticket t = repository.GetTickets().ByTicketID(ticket.TicketID);
    FaultDetail detail;

    try
    {
        //Merge the ticket
        t.ShortDescription = ticket.ShortDescription;
        t.LongDescription = ticket.LongDescription;
        t.IsOpen = ticket.IsOpen;
        t.SeverityLevelID = ticket.SeverityLevelID;
        IEnumerable<RuleViolation> vs = t.GetRuleViolations();
        repository.Save();
    }
    catch (ValidationException vexc)
    {
        detail = new FaultDetail();
        detail.Message = vexc.Message;
        detail.Type = "ValidationException";
        detail.RuleViolations = t.GetRuleViolations().ToList();
        throw new FaultException<FaultDetail>(detail);
    }
    catch
    {
        detail = new FaultDetail();
        detail.Message = "An unknown error occurred updating the ticket";
        detail.Type = "TechnicalException";
        throw new FaultException<FaultDetail>(detail);
    }
}

 

Remembering back to our OnValidate partial method that we added in our validation layer, it simply called IsValid to see if there are any RuleViolations.  If so, OnValidate threw an exception of type ValidationException.  In our update operation, we catch ValidationException.  In that block, we fetch the collection of rule violations and set the RuleViolations property on the FaultDetail.  In this way, we will pass back to Silverlight the server side validations that did not pass.

 

Testing Our Service Layer

As I mentioned earlier, by overloading the constructor of my service class, I left a hook in where I can easily test that layer without issuing an HTTP request.  I’m going to add a couple of tests now.  I am going to put these in a separate test class called TicketServiceTests.  You can see the code here:

TicketService CreateTicketService()
{
    var repository = Fakes.FakeTicketRepository.CreateFakeTicketRepository();
    return new TicketService(repository);
}

Above is a little helper method I created to new up my service class, passing in the FakeRepository.

[TestMethod]
public void Updating_A_Ticket_With_Empty_ShortDescription_Should_Cause_FaultException_Of_FaultDetail()
{
    // Arrange
    var service = CreateTicketService();

    // Act
    var ticket = service.GetTicket(1);
    ticket.ShortDescription = "";
    try
    {
        service.UpdateTicket(ticket);
        Assert.Fail("Validation Issue Should Have Occurred");
    }
    catch (FaultException<FaultDetail>)
    {
        Assert.IsTrue(true);
    }
    catch (Exception exc)
    {
        Assert.Fail("FaultException<FaultDetail> should have been thrown. " +
            exc.GetType().ToString() + " was thrown");
    }
}

Again, I have a very verbose method name.  You can see from this test that we are validating that the appropriate exception type is being thrown when a rule violation occurs.  The next test will ensure that the appropriate RuleViolation is returned with the exception.

[TestMethod]
//Added line break in Method name for blog readability
public void Updating_A_Ticket_With_Empty_ShortDescription_Should_Raise_FaultException_Of_
FaultDetail_Containing_RuleViolation_For_ShortDescription()
{
    // Arrange
    var service = CreateTicketService();

    // Act
    var ticket = service.GetTicket(1);
    ticket.ShortDescription = "";
    try
    {
        service.UpdateTicket(ticket);
        Assert.Fail("Validation Issue Should Have Occurred");
    }
    catch (FaultException<FaultDetail> ex)
    {
        Assert.IsInstanceOfType(
            ex.Detail.RuleViolations.Find(rv => rv.ErrorMessage ==
                Ticket.ShortDescriptionRequired),
                typeof(RuleViolation)
        );
    }
}

 

Summary

In this post, I added the services layer for my little sample app.  Here is a brief summary of what I did:

  1. Added a Web Application Project to the solution
  2. Used the ‘Silverlight-enabled WCF Service’ template to add a service configured with custom binding that wires up a binary encoder.
  3. I had to tidy up a bit.  I added a project and moved some re-usable components to that project.
  4. I added a SilverlightFaultBehavior class.  This will allow Silverlight to see our FaultExceptions.
  5. I update the web.config, configuring our SilverlightFaultBehavior class.
  6. I added a FaultDetail class.  This class allows me to pass info to the caller like a Message, the exception type and a collection of validation errors.
  7. I then coded up the service
    • I added an ITicketRepository field
    • I added the ability to set a fake repository with an overloaded constructor
    • I added the fetch operations
    • I added the update operation. In that operation, I caught the ValidationException. In that catch, I set the appropriate rule violations on the FaultDetail.
  8. I wrote some tests

 

What’s Next

In the next post, I will likely illustrate how the WCF service can be called from a Silverlight component.  I will also illustrate how we are able to pass across exceptions, as well as server-side validation issues.  The following post will get into the Service Agent pattern.

The Bagbys Are Moving to London

As some of you know, my wife Carrie works for American Express in Arizona.  Recently she was offered a great career opportunity in London and we have decided to pursue it.  It was a very difficult decision for us on many levels.  First and foremost, we are leaving behind our friends and family who mean the world to us.  Secondly, I have to leave my job with Microsoft and DPE (Developer and Platform Evangelism).  For over 3 years, I have had the privilege to work for the finest organization in the world with the best team I could imagine.  I am not embellishing when I tell you that for 3 years I have loved going to work.  This job will be hard to equal.

We are both looking forward to the adventure of living in another country, embracing another culture.  What you might not know is that Carrie and I met at Thunderbird, The American Graduate School of International Business, where we both earned Masters Degrees in International Finance.  I know what you’re thinking… Bagby? Finance?  I was young. I needed the money.  Seriously, Carrie and I have always had a passion for experiencing other cultures.  I spent a summer studying German at The University of Heidelberg and a winter in Vienna, while Carrie spent a summer studying Spanish in Spain.  Were a bit older now and not so quick on the uptake, so it is nice that we are moving somewhere where we already know the language.

Carrie has started her new job here in Arizona and has committed to being in London in early January.  As such, Carrie, Jack and I will heading “across the pond” sometime in early December.  I will continue in my current position until then.  I am not yet sure what I will be doing when we get to London.  Various opportunities have presented themselves thanks to the many friends I have made along the way at Microsoft. 

I’ll keep everyone apprised when things are more solid.

Patterns-Based Silverlight Development Blog / Screencast Series Index

I am in the midst of putting together a blog / screencast series illustrating developing Silverlight 3 application, taking advantage of various design patterns.  Some of the patterns we will cover are the Repository, the Pipeline, the Service Agent and Model View ViewModel.  I will be building a Sample HelpDesk Application along the way (see below).

I will keep this post updated with the links to all of the blog posts and screencasts:

Blog Posts

Screencasts

 

 

Screenshot

The following is a screenshot of the sample application we will be creating throughout this series.

image

Next Page »

Demystifying The Code