Sunday, 26 October 2008

Using C# Automatic Properties with XPO Objects - Part 1

In my previous post I touched on the fact that objects in Express Persistent Objects (XPO) support change tracking. One area that this is used by their Unit of Work to track the changes made to objects. Another use is when data binding objects to a UI. So, how do you enable change tracking in your object model using XPO?

XPO supports a variety of methods for achieving this, but the easiest is to inherit your domain objects from XPObject. When you do this change tracking is enabled by calling a magic setter method in your property setters and using their built-in collection type for association properties:

public class Customer: XPObject
{
  private DateTime date;
  public DateTime Date
  {
    get { return date; }
    set
    {
      SetPropertyValue("Date", ref date, value);
    }
  }
  [Association("CustomerOrders", typeof(Order))]
  public XPCollection<Order> Orders
  {
    get { return GetCollection<Order>("Orders"); }
  }
}

Note that Association attribute on the collection property is required by XPO and indicates that the property is one end of a two-way association - either one-many or many-many. Associations are always two-way, except one-one associations which are handled differently. So, for completeness, with the example above being a one-many relationship, you will need the following to express the other end:

public class Order: XPObject
{
  private Customer customer;
  [Association("CustomerOrders")]
  public Customer Customer
  {
    get { return customer; }
    set 
    { 
      SetPropertyValue("Customer", ref customer, value); 
    }
  }  
}

It makes sense to use a collection type that supports change notification and the calls to SetPropertyValue are a fairly elegant way to notify change. Okay, this is all good, but I like to cut down the syntactic noise as far as possible. This basically means that I want to to use C# automatic properties (and I also don't want get into using design time code generation techniques to help me out). So, where do we go from here? We go to this:

[XpoAutomaticProperties]
public class Customer: XPObject
{
  public DateTime Date { get; set; }
  [Association("CustomerOrders", typeof(Order))] 
  public XPCollection<Order> Orders 
  { 
    get; private set; 
  }
}
[XpoAutomaticProperties]
public class Order: XPObject
{
  [Association("CustomerOrders")] 
  public Customer Customer 
  { 
    get; private set; 
  }
}

The classes above will give the same functionality - change tracking and collection creation - as the previous examples. Except, there is much less code to read, just automatic properties and an extra attribute on the class declaration. Take a look at part 2 to see how this can be done.

No comments: