After my last post I said we’d take a look at one to many associations next time, and that’s what we are doing to do now. With it coming up to Christmas I thought we would write a little application to give Santa a hand with his deliveries – I mean the poor old guy’s got a lot of work to do so I figure he could use all the help he can get, right?
So we are going to write an application that will provide him with delivery instructions, detailing which presents to deliver to which house. To do that, the first thing we need is a class to define a house:
using System;
using DevExpress.Xpo;
namespace XPOChristmas
{
public class House : XPObject
{
public House(Session session)
: base(session)
{ }
private string address;
public string Address
{
get
{
return address;
}
set
{
SetPropertyValue("Address", ref address, value);
}
}
private Country country;
public Country Country
{
get
{
return country;
}
set
{
SetPropertyValue("Country", ref country, value);
}
}
[Association("House-Presents")]
public XPCollection<Present> Presents
{
get
{
return GetCollection<Present>("Presents");
}
}
public void ShowDeliveryInstructions()
{
Console.WriteLine(String.Format("Santa, deliver to {0} the following: ", Address));
foreach (Present p in Presents)
{
Console.WriteLine(String.Format(" {0}", p.Description));
}
Console.WriteLine();
}
}
}
As you can see, this class extends XPObject just like you’ve seen in all the XPO example so far. It also has a property detailing the address of the house. This is a simple string property that we’ve seen many times before, so we need not say any more about that.
We need not say too much about the country property either, it simply holds an enum describing the country in which the house is located, the definition of the enum is very simple:
using System;
namespace XPOChristmas
{
public enum Country
{
Scotland,
England,
Ireland,
Wales
}
}
The next property however, is a little special. This property holds the child relationship with all the presents that are due to be delivered to this house. The first thing to notice about the property is that it is decorated with the Association attribute. This attribute must be unique in the database and the string name must match on both the parent and child ends of the association. Note the use of the helper function GetCollection<T> which returns all the children in the association.
The last thing to notice about this class is the ShowDeliveryInstructions() method that displays instructions for the house and then walks the graph of children and displays instructions for them.
The next thing we need then is a class to describe the presents:
using System;
using DevExpress.Xpo;
namespace XPOChristmas
{
public class Present : XPObject
{
public Present(Session session)
: base(session)
{ }
private string description;
public string Description
{
get
{
return description;
}
set
{
SetPropertyValue("Description", ref description, value);
}
}
private House house;
[Association("House-Presents")]
public House House
{
get
{
return house;
}
set
{
SetPropertyValue("House", ref house, value);
}
}
}
}
This class has a Description property which we need not say too much about and also a property which points to it’s parent house. Note the association attribute decorating the property and pay particular attention to the fact that the name is the same name that is on the parent end of the association.
Once we have those two classes we just need code to drive it all:
using System;
using System.Linq;
using DevExpress.Xpo;
namespace XPOChristmas
{
class Program
{
static void Main(string[] args)
{
//GS - Persist some houses and presents for Santa
using (UnitOfWork uow = new UnitOfWork())
{
House house = new House(uow)
{
Address = "27 Cromarty Road",
Country = Country.Scotland
};
new Present(uow)
{
Description = "Little Blue Car",
House = house
};
new Present(uow)
{
Description = "Big Book For Boys",
House = house
};
House nextHouse = new House(uow)
{
Address = "27 Chelsea Lane",
Country = Country.England
};
new Present(uow)
{
Description = "Little Pink Car",
House = nextHouse
};
new Present(uow)
{
Description = "Big Book For Girls",
House = nextHouse
};
uow.CommitChanges();
}
//GS - Get delivery instructions for all houses
Console.WriteLine("Displaying all houses...");
Console.WriteLine();
using (UnitOfWork uow = new UnitOfWork())
{
XPQuery<House> houseQuery = new XPQuery<House>(uow);
foreach (var house in houseQuery)
{
house.ShowDeliveryInstructions();
}
}
//GS - Get delivery instructions for the house in Scotland
Console.WriteLine("Displaying Scottish houses...");
Console.WriteLine();
using (UnitOfWork uow = new UnitOfWork())
{
XPQuery<House> houseQuery = new XPQuery<House>(uow);
var houses = from h in houseQuery
where h.Country == Country.Scotland
select h;
foreach(var house in houses )
{
house.ShowDeliveryInstructions();
}
}
}
}
}
In this code we persist some house and present objects and then retrieve them from the database before asking them to display their delivery instructions. There is nothing really special to say about this code, we have seen many such examples. The only thing to note is that the one to many associations can be specified from either end. In this case I specify it from the child side, because I found that most convenient, but either will do.
Now that I have shown you the code, all that remains is to run it:
And that is it really, with such good help how could Santa fail to get all his presents delivered on time? That brings this post to a close, so until next time, happy XPOing! :-)