Wednesday, February 15, 2006

A neat way of getting around some OR mapping issues with temporary Domain classes.

I recently discovered a nice pattern for dealing with self joins, and many-to-many joins in a Data Access Layer. Here's the problem. In your domain design you have an class with a collection of itself. This is a common pattern for tree structures.
class MyEntity
{
   MyEntityCollection _myEntities;

   MyEntityCollection MyEntities
   {
       get{ retrun _myEntities; }
   }
}
To do a similar thing in a relational database one would normally have two tables, the entity table and a table to map the relationships between the entities.
create table MyEntity(
   id int
)

create table MyEntityMap(
   from_id int,
   to_id int
)
Now, how do we recreate object map in memory from the relational data. My solution is to use a temporary domain class to represent the map table. It has a reference to the entities on both ends of the relationship and a method to wire them up.
class MyEntityMap
{
   MyEntity _fromEntity;
   MyEntity _toEntity;

   public void WireUp()
   {
       _fromEntity.MyEntities.Add(_toEntity);
   }
}
The MyEntityMapCollection class has a method WireUp() that calls WireUp() on every MyEntityMap object.
class MyEntityMapCollection
{
   ArrayList _myEntityList = new ArrayList();

   ...

   public void WireUp()
   {
      foreach(MyEntity myEntity in _myEntityList)
      {
         myEntity.WireUp();
      }
   }
}
Then in our data access layer we can simply get all the MyEntity objects from the database, storing pointers to them in an object store, then get all the MyEntityMap objects. Each MyEntityMap object gets the pointers for the correct objects from the object store. The last task is to call WireUp() on the MyEntityMapCollection. Here's the DAL code.
public MyEntity GetEntityMap()
{
   MyEntityCollection myEntities = SelectAllEntitiesStoredProcedureWrapper();
   MyEntityMapCollection myMap = SelectAllEntityMapStoredProcedureWrapper();
   myMap.WireUp();

   // some method to get the root MyEntity
   return GetRootEntity(myEntities);
}

2 comments:

Ralf Westphal - One Man Think Tank said...

Hi, Mike! How did you get the source code in your posting so neatly formatted? I´m struggling to do the same in my blog. I´d apreciate any hint! Thx in advance!

-Ralf (info[at]ralfw.de)

Mike Hadlow said...

Hi ralf, I just do put all the code inside pre tags:

<pre>
code
</pre>