Sunday, April 25

Lazy Load Eager Debugging

In the project I'm currently working on we have entity model which use Lazy Loading fetch of properties. Wether it is a property referring to another entity or collection of entities we load it lazy. The same thing can be configured if you use NHibernate for your entity model.

Another thing is that debugger and specifically Visual Studio Watch window is not so friendly to lazy loading because the Watch window try to evaluate the value of each property which cause all the lazy loading properties to be loaded.

To overcome this problem Visual Studio offer several options: DebuggerDisplay and DebuggerTypeProxy both from System.Diagnostics namespace.
The former simply use a string to override the string display for the entity instance itself. It is not very helpful and does not work well with inheritance.

The later, DebuggerTypeProxy, is very useful in this case. It allow us to tell the Watch window to use a proxy class when watching on the properties of the real class and by doing so prevent any lazy loading properties from been evaluated just because we watch them.
DebuggerTypeProxy also works great with inheritance since you can inherit your proxy class from another proxy class and by doing so create hierarchy of proxies, each of which display information about it own level in the hierarchy.

Off couse the Watch window still allow the developer to watch on the raw instance itself, but remember that doing so will cause any lazy property to be evaluated.

Here is a sample code:

   1:  [DebuggerTypeProxy(typeof(ClientDebuggerProxy))] class Client {

   2:  private string name;

   3:  private Client wife;


   5:  public Client Wife

   6:  {

   7:  get {

   8:  if (wife == null) wife = LazyLoadWife();

   9:  return wife;

  10:  }

  11:  }

  12:  internal class ClientDebuggerProxy

  13:  {

  14:  private Client client;

  15:   // The constructor for the type proxy class must have a

  16:   // constructor that takes the target type as a parameter.

  17:   public ClientDebuggerProxy(Client client)

  18:   {

  19:    this.client = client;

  20:   }

  21:  public Client Wife

  22:  {

  23:  // Notice we return lower case wife, which is a field.

  24:  get { return client.wife; }

  25:  }

  26:  }

  27:  }

As you can see from this simple sample, we have a Client class which has lazy property Wife. On the debugger proxy class we return the wife field instead of lazy loading it so we can use the Watch window to see the real state of the instance without changing it.

No comments:

Post a Comment