Wednesday, January 14, 2009

Traverse Business Instances

Introduction
LINQ to SQL updated the way that we implement DAL with ADO.Net code. It actually wraps ADO.Net and provides a higher level of abstraction. However, we not only need to simply access entities, but also need to traverse entities that has logical business relationships.


Map the Relationships and Enforce Integrity

Under LINQ to DB, relationship is mapped and referential integrity is enforced. Suppose in relational db, we have a customers table which has a 0-m relationship to orders table, the following is how LINQ mapped:

Class Customer
{
[Association(Name="FK_Orders_Customers",
Storage="_orders",
OtherKey="CustId",
DeleteRule="NoAction"
)]
public EntitySet<Order> Orders
{
get{return this_orders;}
set{this._orders.Assign(value);}
}

private EntitySet<Order> _orders;

}

Scenarios Where Traverse is Needed

For DAL it is perfect. However, it seems there is still a gap to meet business layer requirements. From business point of view, we not only need to access persisted entities, but also need a way to easily walk through logically related entities. The walks happen in the following cases:

1. Get all orders of a customer

Customer customer = AutoContext.Customers.FindOne(customer.id==123);
EntitySet<Order> orders = customer.Orders;


2. Suppose we have a representatives table which has a 0-m relationship to customers, then we want to know the representative

of a customer.

in above example, unfortunately it doen't have a reference to "parent" table, but we expect to code like the following:

Representative r = customer.Representive;


3. In case of m-m relationship

suppose there are three tables:

Customers, Customers_Plans, and Plans
Between Customers and Plans is a m-m relationship implemented by Customers_Plans table.

We need to get all plans a customer regisered with code like the following:

EntitySet<Plan> plans = customer.Plans;

instead of:

EntitySet<Customers_Plans> [note here the naming issue for compound word] cps = customer.Customers_Plans;

EntitySet<Plan> plans = new EntitySet<Plan>();
foreach(cp in cps)
{
plans.Add(cp.Plan);
}


4. Among other case, we have a set of customers and want get the plans that there is at least one customer who has

registered; or we may need get the plan that all customers registered.

No comments: