Implementing Child Collections

 

Project Page

Download

Manual

Overview
Hello SPF
Attributes
Constraints
Triggers
Criteria
Child Collections

You will come across parent-child relationship in all but the most trivial of systems. SPF supports such relationships through the use of SpfChildCollection objects.To show how this is done we will turn to the tried and trusted Order and Order Line example.

First we create an OrderLine entity with nothing out of the ordinary:

	[SpfTypeStorage(TableName = "tbOrderLines")]
	public class OrderLine : SpfEntity {

		public Guid OrderId;

		public string Description = "";

		public double Price = 0;

		public int Quantity = 0;

	}

Next we create an Order object and we specify that it contains a collection of order lines by having a field of type SpfChildCollection as follows:

	[SpfTypeStorage(TableName = "tbOrders")]
	public class Order : SpfEntity {

		public string Description = "";

		[SpfChildStorage(ChildType = typeof(OrderLine), ForeignKey = "OrderId")]
		public SpfChildCollection OrderLines;

	}

The child collection must have a corresponding SpfChildStorage attribute which specifies the type of entity that the collection contains and the foreign key field on the child entity. This field must be of type Guid.

The following code shows an order being created with 10 order lines:

	Order order = new Order();
	order.Description = "A special treat";

	for (int i = 0; i < 10; i++) {

		OrderLine orderLine = new OrderLine();
		orderLine.Description = "OrderLine " + i;
		orderLine.Price = i + 1.99;
		orderLine.Quantity = 11 - i;

		order.OrderLines.Add(orderLine);

	}

	order = (Order)broker.Persist(order);

As you would expect, retrieving an object with children by default retrieves all the children and grandchildren and so on. This is not always the desired behaviour and so you can specify a maximum depth when doing entity retrieval. For example the code below retrieves the order, but not the order lines:

	order = (Order)broker.Retrieve(typeof(Order), order.Id, 0);

A runtime exception is thrown if any attempt is made to access any property of the order lines collection apart from IsLoaded. This can be used to implement lazy loading as follows:

	if (!order.OrderLines.IsLoaded) {
		order.OrderLines.Load(broker);
	}

The order lines collection can now be used as the following example shows:

	ArrayList removedOrderLineList = new ArrayList();


	foreach (OrderLine orderLine in order.OrderLines) {
		if (orderLine.Quantity % 2 == 0) {
			removedOrderLineList.Add(orderLine);
		}
		else {
			orderLine.Price *= 100;
		}
	}


	foreach (OrderLine removedOrderLine in removedOrderLineList) {
		order.OrderLines.Remove(removedOrderLine);
	}


	order = (Order)broker.Persist(order);

If the quantity is even then the line is removed, otherwise the price is multiplied by 100. When the order is persisted then the removed lines are deleted from the store and the updated items are saved.

Deleting an entity causes all their children to be deleted and, of course, their grandchildren too and so on:

	m_DeptBroker.Delete(order);

We have now seen how to declare and use a child collection in SPF. We have also seen that you can have hierarchies of arbitrary depth and that the application code can take advantage of lazy loading.