Jun 30 2009

Nvigorate Alpha Release 0.8.1.0 – Dynamic WCF Proxy

Category: NvigorateAlexRobson @ 14:45


So today I found a pretty huge error in the guts of Nvigorate. I’m still not clear how I managed to ignore the broken unit tests (sorry all) but now they’re all passing again. The exception occurred when attempting to use Reflector to read/write from static members and was introduced at some point when I added the caching functionality to Reflector (which greatly improves the performance of several things in the framework).

The positive addition to Nvigorate since the last point release is the beginnings of dynamic WCF proxy client(s) called ServiceClient (catchy, right?) My primary reason for creating this is my passionate hatred of SvcUtil and all the little headaches of the code it generates. It’s very new code so you shouldn’t expect a lot of bells and whistles but it does allow you to create WCF service proxies without a lot of overhead. You can choose to configure the client entirely through code, through configuration, or, my personal favorite, from the MEX endpoint of the service itself. The nice thing about that last option is that the binding can change and (most of the time) you won’t have to make changes to your code, the client configures itself based on the metadata it receives from the service.

Here’s a quick example of two ways to use the client

// Very simple service implementation

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string ReturnString(string input);
}

public class TestService : ITestService
{
    public string ReturnString(string input)
    {
        return input;
    }
}

// ServiceClient's IDisposable implementation provides
// channel management so the channel is properly closed
// and disposed of once you're done with it.

using (var client = new ServiceClient<ITestService>(_address))
{
    var returned = client.Proxy.ReturnString("test");
}


// This approach will open/close/abort the channel
// for the single call. It also provides try/catch/finally
// and logging hooks to provide a slightly more robust user
// experience

using (var client = new ServiceClient<ITestService>(_address))
{
    var returned = client.Call(c => c.ReturnString("test"));
}

Tags:

Apr 3 2009

Nvigorate - Lazy Loading

Category: NvigorateAlexRobson @ 09:02

Any serious ORM has lazy loading. But can your ORM lazy load across a remoting boundary? Nvigorate's lazy loading is a function of the state tracking now which works through AOP using the PostSharp framework. I always had some conceptual idea of how I wanted the lazy loading to work through an AOP model but wasn't positive how to implement it so that it would work across remoting boundaries and/or a 2-tier application.

Currently, the IRepository interface has GetRelative and GetRelatives methods which make loading relatives to an instance (regardless of their relationship) a trivial affair. Here's a super-simple example:

   1: var repository = new DatabaseRepository("simple"); // simple is the repository name/connection string name
   2:  
   3: // this Get call overload takes the primary key value(s) that identify the record
   4: // this call will only load the requested instance, not the child records
   5: var person = repository.Get<Person>("123-45-6789");
   6:  
   7: // this GetRelatives call retrieves the related vehicles in the database for the
   8: // person record I loaded
   9: var vehicles = repository.GetRelatives<Vehicle, Person>(person);

 

Could that be any simpler? Well, actually it could. We could implement lazy loading. Now, some frameworks required you to implement the child properties as special types instead, but Nvigorate tries very hard to limit the amount of requirements on your class. Let's take a quick look (for refresher sake or if you're new to Nvigorate) at the definition for the Person and Vehicle classes:

   1: [PersistenceStateAspect]
   2: public class Person : PersistenceState
   3: {
   4:     public List<Address> Addresses { get; set; }
   5:     public string FirstName { get; set; }
   6:     public string LastName { get; set; }
   7:     public DateTime DateOfBirth { get; set; }
   8:     public string SocialSecurity { get; set; }
   9:     public List<Vehicle> Vehicles{ get; set; }
  10: }
  11:  
  12: [PersistenceStateAspect]
  13: public class Vehicle : PersistenceState
  14: {
  15:     public string Vin { get; set; }
  16:     public string Model { get; set; }
  17:     public int Year { get; set; }
  18:     public string OwnerSocial { get; set; }
  19: }

 

The PersistenceStateAspect attribute is required in order to get automated dirty-tracking. These classes must implement IPersistable and PersistenceState is a friendly out-of-the-box base class provided for you. The reason I'm showing you this code is I want you to notice that both Addresses and Vehicles are List<> types and not some other special base class. But we're not entirely done just yet if we want lazy loading. In the example I just showed you, lazy loading is off. Sometimes you'll want this behavior to control when children are loaded. You'll understand why in a moment.

If we want to turn lazy loading "on" for the Person class, we'd just change the attribute declaration to this:

   1: [PersistenceStateAspect(typeof(DatabaseLazyLoader<,>), "simple", true)]


Ok, I have lots of 'splaining to do. The first argument is a concrete class that handles the actual lazy load call. DatabaseLazyLoader is another Nvigorate type that handles the 2-tier version where the call doesn't need to cross a remoting boundary. The <,> after the type is required but we don't provide generic arguments now because all we're doing is telling Nvigorate which class will facilitate the calls to load the child during runtime. DatabaseLazyLoader inherits an abstract base class called BaseLazyLoader which takes the generic parameters for the parent and child types and has two calls: LoadInstance and LoadCollection.

The Aspect's advice uses a class called LazyLoadingProxy which instantiates the BaseLazyLoader implementation (in our example, DatabaseLazyLoader) and makes the appropriate call. In case any of this sounds intimidating to you: the amount of code required to implement all this stuff is near trivial. The only complexity introduced is in the advice code, which you actually never need to worry about. You can completely control the LazyLoading by inheriting BaseLazyLoader and providing that type in the PersistenceStateAspect attribute. Just to prove I'm not fibbing, here's the source code for DatabaseLazyLoader:

   1: public class DatabaseLazyLoader<T, S> : BaseLazyLoader<T,S>
   2:         where T : class, IPersistable, new()
   3:         where S : class, IPersistable, new()
   4:     {
   5:         protected DatabaseRepository _repository;
   6:  
   7:         public override T LoadInstance(S parent)
   8:         {
   9:             return _repository.GetRelative<T, S>((S)parent);
  10:         }
  11:  
  12:         public override IEnumerable<T> LoadCollection(S parent)
  13:         {
  14:             return _repository.GetRelatives<T, S>((S)parent);
  15:         }
  16:  
  17:         public DatabaseLazyLoader(string repositoryName) : base(repositoryName)
  18:         {
  19:             _repository = new DatabaseRepository(repositoryName);
  20:         }
  21:     }


I'm sure at this point, you can imagine how I can now get this to work across a remoting boundary. Just wire a service reference to the Service contract for your favorite IRepository implementation and viola. Not difficult enough? You can get lazy loading to work any way you like. So let's talk about the other two arguments. The second argument in the list, if you hadn't figured it out already is the repository name. I don't feel like I need to explain that a lot here, so let's move to the last and very important argument which is controls what the advice does after it loads the children.

In some scenarios, you may not want the lazy loaded children to be written to the parent's property. I think those scenarios are few and far between, but who am I to judge, right? If you pass true into the attribute, the advice will write the result into the parent's property. In our example, I've passed true in which means that after the lazy loader gets all the child vehicles for my person from the database, it's going to write those instances into the Vehicles property. This prevents the advice from re-calling the lazy loader again unless you null or empty the child collection. The opposite is also true: if you don't cache, the lazy loader will re-load the children from the database every single time you access the property's getter. Every. Single. Time. Here are some examples of what I mean:

   1: // first we just get the person without eager loading
   2: // the lazy loader does not get called during a normal fetch
   3: var person = repository.Get<Person>("123-45-6789");
   4:  
   5: // with caching set to false on the PersistenceStateAspect attribute
   6: // every one of these lines will cause the lazy loader to re-load
   7: // the child objects
   8:  
   9: int vehicleCount = person.Vehicles.Count; 
  10:  
  11: var newVehicles = person.Vehicles.First(v => v.Year >= 2009);
  12:  
  13: if (person.Vehicles != null)
  14: {
  15: }
  16:  
  17: person.Vehicles.Add(new Vehicle() { Model="Equinox", Year=2007 });
  18:  
  19:  


The last two might be a bit more surprising but realize that the lazy load fires when a parent instance's child property is accessed through the property's getter. So any reference to it at all causes the load to happen. This has the same effect as trying to open a refrigerator door fast enough to determine if the light is ever off. As soon as you open the door you trigger the light. Same idea here, as soon as you access the property, Nvigorate fetches a result if there wasn't already one provided. Rest assured, I have done a lot of debugging to make sure that there's "nothing up the sleeve" before the load happens.

Hopefully after this discussion, you realize why you may not always want to use this feature because it takes control out of your hands. Especially if you have any kind of generic instance handling happening: if anything accesses that property a load happens. Obviously this could introduce a lot of unintentional traffic and over-head especially if an object had hundreds of children.

But sometimes lazy loading is exactly what you want: imagine it in the simple context of a site which has a single master record and lots of child records which you may or may not be displaying at any given time. You could simply cache the master record and any time you needed to display a child/children, you simply access the child property and that's all there is.

Nvigorate's release will include service contracts and WCFLazyLoader and a few other getting started classes to support lazy loading across a WCF boundary out of the box.

As always, feedback is a highly sought after thing!

Tags: