How to map a tree in NHibernate

Introduction

Lately there have been many questions regarding how to best map a tree structure in NHibernate. In this post I'll try to show you various techniques how one can deal with a tree structure.

The code for this sample you can get from here.

Domain Model

Let's define a very simple domain model for this sample. We have a single class called Equipment that has a parent of type Equipment and 0 to many children of type Equipment. The tree has a single root node. The root node is specific by the fact that it's property Parent is equal to null. On the other hand a tree has leaf nodes. A leaf node is defined to have no children.

You could as well replace the class Equipment by e.g. a Person class. The principles shown here would not change.

image

Where is my Aggregate?

A Aggregate in DDD is defined as "A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the Aggregate, designated as the root. A set of consistency rules applies within the Aggregate's boundaries."

Depending on our Use Cases or User Stories we can define our Aggregate either as

image

that is, the aggregate includes the equipment (which is the root) and its children.

Or we could define the Aggregate as follows

image

here only the equipment object is part of the aggregate (it is at the same time the root of the aggregate).

In the following I choose the former aggregate (equipment and children). This corresponds to the use case where I want to edit an equipment and its children in a single business transaction.

Note: Normally one defines a Repository for each Aggregate in the domain model.

Mapping

Let's have a look at the mapping for the Equipment class.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="TreeStructure"
                   namespace="TreeStructure">
  <class name="Equipment">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Name" length="50" not-null="true" unique="true"/>
    
    <many-to-one name="Parent" class="Equipment" column="ParentId" />
    
    <set name="Children" cascade="all-delete-orphan" >
      <key column="ParentId" foreign-key="fk_Equipment_ParentEquipment"/>
      <one-to-many class="Equipment"/>
    </set>
  </class>
</hibernate-mapping>

The name property of the equipment must be defined and unique. The name can be at most 50 characters long.

The parent property is not mandatory (this is the default, i.e. not_null=false) since the root node has Parent equal to null.

I have defined the children collection as a Set, that is an unordered collection of unique objects.  I have chosen cascade="all-delete-orphan" to instruct NHibernate that he automatically saves, updates or deletes the children of an equipment too when I save, update or delete the equipment. I also have defined that the foreign key constraint that will be defined on the database between the equipment and its parent has a friendly name (fk_Equipment_EquipmentParent).

Now I can write a unit test to check whether NHibernate can create the correct schema for me. In this sample I use a SQL Server 2005 database (the express edition is ok too) since later on I want to show some specific features only available in SQL Server. The code of the test is

[Test]
public void Can_generate_schema()
{
    var configuration = new Configuration();
    configuration.Configure();
    configuration.AddAssembly(typeof (Equipment).Assembly);
 
    // show the schema for debugging purposes
    new SchemaExport(configuration).Execute(true, false, false, false);
 
    // generate the schema in the database
    new SchemaExport(configuration).Execute(false, true, false, false);
}

This test runs successfully and generates the following output (SQL script)

if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_Equipment_ParentEquipment]') 
           AND parent_object_id = OBJECT_ID('Equipment'))
  alter table Equipment  drop constraint fk_Equipment_ParentEquipment
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'Equipment') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
  drop table Equipment
 
create table Equipment (
  Id UNIQUEIDENTIFIER not null, 
  Name NVARCHAR(50) not null unique, 
  ParentId UNIQUEIDENTIFIER null, 
  primary key (Id)
)
 
alter table Equipment 
add constraint fk_Equipment_ParentEquipment 
foreign key (ParentId) references Equipment
The first part of the script drops the database objects if they are already there and in the second part of the script the table Equipment is generated as well as the foreign key constraint between the equipment and its parent. The create script for the table looks exactly like expected.

The Repository

A Repository is defined as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects."

As said above, for each Aggregate in the domain model one defines a Repository. Since we only have one aggregate in our simple domain we also will have only one repository. Let us call it EquipmentRepository.

Now I want to be able to eager load the complete aggregate given the id of the aggregate root. I write the following unit test

[Test]
public void Can_load_aggregate_by_id()
{
    var equipmentId = ...;    // some id
    var equipment = _repository.GetAggregateById(equipmentId);
    Assert.IsNotNull(equipment);
    Assert.IsTrue(NHibernateUtil.IsInitialized(equipment.Parent));
    Assert.IsTrue(NHibernateUtil.IsInitialized(equipment.Children));
    Assert.AreEqual(3, equipment.Children.Count);
}

With this test I assert that a) I get an aggregate and b) the aggregate is fully populated. To check whether the aggregate is fully populated I use the NHibernateUtil utility class. The test assumes the existence of a equipment tree fragment in the database. Please refer to the project (here) for any details how I create this tree fragment in the SetUp of the test fixture.

A possibility to eager load an aggregate is by using a HQL query as below

public Equipment GetAggregateById(Guid equipmentId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Equipment e" +
                  " left join fetch e.Parent p" +
                  " left join fetch e.Children c" +
                  " where e.Id = :id";
        var equipment = session.CreateQuery(sql)
            .SetGuid("id", equipmentId)
            .UniqueResult<Equipment>();
        return equipment;
    }
}

I use left joins since either Parent can be null or the equipment has no children. The SessionManager class is a helper class which I use to provide me session objects. Please have a look at the project which you can find here for any details.

Finding the root aggregate is easy. We just have to look for an equipment whose parent is equal to null

public Equipment GetRootAggregate()
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Equipment e" +
                  " left join fetch e.Children c" +
                  " where e.Parent is null";
        var equipment = session.CreateQuery(sql)
            .UniqueResult<Equipment>();
        return equipment;
    }
}

Now some times we want to find all leaf nodes of the tree. Remember that a leaf node has by definition no children. We could use the following code for this

public ICollection<Equipment> GetAllLeafNodes()
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Equipment e" +
                  " left join fetch e.Parent p" +
                  " where e.Children.size = 0";
        var leafs = session.CreateQuery(sql)
            .List<Equipment>();
        return leafs;
    }
}

here we use the handy size function for collections provided by HQL. Note that this method delivers all leaf nodes of the tree. To only select the leaf nodes of a sub-tree starting at a given equipment node is trivial now and I leave for you as an exercise.

Eager load ancestors and descendants

To eager load all ancestors or descendants of a given equipment node we have to use native TSQL since HQL (as well as the criteria API) does not provide a generic way of doing it. Fortunately SQL server 2005 provides us the means to achieve the desired result. We have to construct a hierarchical query as below

public ICollection<Equipment> GetAllDescendantsOfEquipment(Guid equipmentId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "with Hierachy(Id, Name, ParentId, Level)" +
                  " as" +
                  " (" +
                  "   select Id, Name, ParentId, 0 as Level" +
                  "   from Equipment e" +
                  "   where e.Id = :id" +
                  "  union all" +
                  "   select e.Id, e.Name, e.ParentId, eh.Level + 1" +
                  "   from Equipment e" +
                  "   inner join Hierachy eh" +
                  "      on e.ParentId = eh.Id" +
                  " )" +
                  " select Id, Name, ParentId" +
                  " from Hierachy" +
                  " where Level > 0";
        var list = session.CreateSQLQuery(sql)
            .AddEntity(typeof(Equipment))
            .SetGuid("id", equipmentId)
            .List<Equipment>();
        return list;
    }
}

The last where statement in the SQL assures that the given equipment is not included in the list of descendants.

Analogous we can get the list of ancestors of a given equipment node

public ICollection<Equipment> GetAllAncestorsOfEquipment(Guid equipmentId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "with Hierachy(Id, Name, ParentId, Level)" +
                  " as" +
                  " (" +
                  "   select Id, Name, ParentId, 0 as Level" +
                  "   from Equipment e" +
                  "   where e.Id = :id" +
                  "  union all" +
                  "   select e.Id, e.Name, e.ParentId, eh.Level + 1" +
                  "   from Equipment e" +
                  "   inner join Hierachy eh" +
                  "      on e.Id = eh.ParentId" +
                  " )" +
                  " select Id, Name, ParentId" +
                  " from Hierachy" +
                  " where Level > 0";
        var list = session.CreateSQLQuery(sql)
            .AddEntity(typeof(Equipment))
            .SetGuid("id", equipmentId)
            .List<Equipment>();
        return list;
    }
}

Note that we had just to adjust the inner join between the Equipment table and the Hierarchy (temp) table. Again the last where statement in the SQL assures that the given equipment is not included in the list of ancestors.

An alternative approach

We can also choose another approach for the tree problem. The solution I want to show works for any database even if it does not support hierarchical queries. This time our simple domain model looks as follows

image

Here we have a node object which can have a parent and a collection of children. Additionally we have defined the two collections descendants and ancestors which contain all descendants (children, children of the children and so on) and all parents of the given node.

The code for the Node class is given by

public class Node
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Node Parent { get; set; }
    public ISet<Node> Children { get; set; }
 
    public ISet<Node> Ancestors { get; set; }
    public ISet<Node> Descendants { get; set; }
}

The mapping for the node is defined as

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="TreeStructure"
                   namespace="TreeStructure">
  <class name="Node">
    <id name="Id">
      <generator class="guid"/>
    </id>
    <property name="Name" length="50" not-null="true" unique="true"/>
 
    <many-to-one name="Parent" class="Node" column="ParentId" />
 
    <set name="Children" inverse="true" cascade="all" >
      <key column="ParentId" foreign-key="fk_Node_ParentNode"/>
      <one-to-many class="Node"/>
    </set>
 
    <set name="Descendants" table="NodeHierarchy" inverse="true" >
      <key column="ParentId" foreign-key="fk_HierarchyNode_ParentNode"/>
      <many-to-many class="Node" column="ChildId" foreign-key="fk_HierarchyNode_ChildNode" />
    </set>
 
    <set name="Ancestors" table="NodeHierarchy" >
      <key column="ChildId" /> 
      <many-to-many class="Node" column="ParentId" /> 
    </set>
  </class>
</hibernate-mapping>

Note that we define the descendants and ancestors of a node as a many-to-many relation in the database. So the SQL script created by the SchemaExport class of NHibernate is

if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_Node_ParentNode]') 
           AND parent_object_id = OBJECT_ID('Node'))
  alter table Node  drop constraint fk_Node_ParentNode
 
if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_HierarchyNode_ChildNode]') 
           AND parent_object_id = OBJECT_ID('NodeHierarchy'))
  alter table NodeHierarchy  drop constraint fk_HierarchyNode_ChildNode
 
if exists (select 1 from sys.objects 
           where object_id = OBJECT_ID(N'[fk_HierarchyNode_ParentNode]') 
           AND parent_object_id = OBJECT_ID('NodeHierarchy'))
  alter table NodeHierarchy  drop constraint fk_HierarchyNode_ParentNode
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'Node') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
  drop table Node
 
if exists (select * from dbo.sysobjects 
           where id = object_id(N'NodeHierarchy') 
           and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
  drop table NodeHierarchy
 
create table Node 
(
  Id UNIQUEIDENTIFIER not null, 
  Name NVARCHAR(50) not null unique, 
  ParentId UNIQUEIDENTIFIER null, 
  primary key (Id))
 
create table NodeHierarchy 
(
  ParentId UNIQUEIDENTIFIER not null, 
  ChildId UNIQUEIDENTIFIER not null, 
  primary key (ParentId, ChildId)
)
 
alter table Node add constraint fk_Node_ParentNode 
foreign key (ParentId) references Node
 
alter table NodeHierarchy add constraint fk_HierarchyNode_ChildNode 
foreign key (ChildId) references Node
 
alter table NodeHierarchy add constraint fk_HierarchyNode_ParentNode 
foreign key (ParentId) references Node

we can see here that the script creates a n-to-m mapping table called NodeHierarchy as well as the necessary foreign keys between this table and the table Node.

To account for this special situation I define an AddChild method on the Node class

public virtual void AddChild(Node childNode)
{
    Children.Add(childNode);
    childNode.Parent = this;
    childNode.Ancestors.AddAll(this.Ancestors);
    childNode.Ancestors.Add(this);
    this.Descendants.Add(childNode);
}

This method is responsible for the book-keeping when adding a new child node to an existing node.

If I now want to eager load a node given by its id with all collections populated then I can use code similar to this one

public Node GetAggregateById(Guid nodeId)
{
    using (var session = SessionManager.OpenSession())
    {
        var sql = "from Node e" +
                  " left join fetch e.Parent p" +
                  " left join fetch e.Children c" +
                  " where e.Id = :id";
        var node = session.CreateQuery(sql)
            .SetGuid("id", nodeId)
            .UniqueResult<Node>();
 
        // load the ancestors
        var sql2 = "from Node e" +
                  " left join fetch e.Ancestors a" +
                  " where e.Id = :id";
        node = session.CreateQuery(sql2)
            .SetGuid("id", nodeId)
            .UniqueResult<Node>();
 
        // load the descendants
        var sql3 = "from Node e" +
                  " left join fetch e.Descendants d" +
                  " where e.Id = :id";
        node = session.CreateQuery(sql3)
            .SetGuid("id", nodeId)
            .UniqueResult<Node>();
 
        return node;
    }
}
For an in depth discussion of how to eager load a complex object graph please refer to this post.
Note that depending on the depth of the tree you should eventually avoid to eager load the descendants collection since this collection can become huge... In may sample I assume a tree with limited depth (e.g. less than 5) and a limited amount of children per node (e.g. less than 5).
 
Enjoy
Blog Signature Gabriel .

Print | posted on Wednesday, May 14, 2008 10:19 AM

Comments on this post

# re: How to map a tree in NHibernate

Requesting Gravatar...
We used this type of approach in a project at work and all was well until our tables started getting big and finding all the elements of the tree using joins started taking a long time.

In the end we used the approach of defining a property of each tree item that refers to the root of the tree; that way we could simply query for an object and all other objects that share the same root to retrieve the entire tree. This approach also allowed us to index the root id for faster retrieval.
Left by Symon Rottem on May 15, 2008 7:36 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
please,when i test the one-to-many releation,i get a exception ,i using nhibernate 2.0 ,can you help me?
Left by coundy on Dec 29, 2008 4:32 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
@coundy: can you provide more details?
Left by nhibernate on Jan 08, 2009 1:45 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Great article, thanks
Left by Barbaros Alp on Feb 16, 2009 7:12 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
You mentioned "To only select the leaf nodes of a sub-tree starting at a given equipment node is trivial now", I can not find an easy way to do this. Can you give me some hints?
Left by Hao on Mar 08, 2009 3:34 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Did you forget to add childNode to the Descendants of all the ancestor nodes in method AddChild()?
Left by Gregor Slavec on Jun 02, 2009 10:09 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Humm... interesting,

I liked the way it worked

Thanks for bringing this up
Left by software development company on Aug 20, 2009 2:29 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
I've tried it, but it doesn't work: the reason is that it is trying to set the property ParentId, which doesn't exist. I tried renaming it to "Parent.Id", but no luck.
Left by Ricardo Peres on Sep 08, 2009 3:30 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Can you give me some directions on how to map an order attribute? In my I must save the order of the child nodes.

Thanks in advance
Fabio
Left by Fábio on Oct 03, 2009 12:01 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Great article, I'm gonna bookmark this
Left by heartworm medicine on Oct 07, 2009 2:59 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Great post, thanks
Left by Carnival cruise on Dec 06, 2009 7:58 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Nice Post. In the alternative solution, wouldn't you also need:

public virtual void AddChild(Node childNode)
{
Children.Add(childNode);
childNode.Parent = this;
childNode.Ancestors.AddAll(this.Ancestors);
childNode.Ancestors.Add(this);
this.Descendants.Add(childNode);
// and now :
this.Descendants.AddAll(childNode.Descendants);
}

Just in case you added a child node which already had descendants, for example if you moved the child node from another parent?
Left by Ramin on Dec 17, 2009 7:30 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
What about the aggregate root in the alternative solution? It would always be the topmost (root) node, because you always change all ancestors when, for example, adding a child node. How does that perform with concurrency issues? Any ways around having the root as the aggregate root? Or am I wrong by saying so?
Left by Ramin on Dec 17, 2009 7:45 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
or example, adding a child node. How does that perform with concurrency issues? Any ways around having the root as the aggregate root? Or am I wrong by saying so?
Left by pandora jewelry on Dec 24, 2009 11:56 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Hi!your article is great!
I want to translate it to mother tongue - Indian(hindi) and post it at my blog, may I?
I want to say something about this is that ,I disagree with the comments regarding the article and TDD. It shows case by case functionality being added.
Left by http://www.casinopoker888.com/ on Dec 29, 2009 4:46 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
agreed tt
Left by make money online on Jan 16, 2010 1:17 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
NHibernate is a cool but its mapping was a real headache for me. I was quite confused with the codes that created the problems. While working with the children collection I made an error and that was the main problem.
Left by Predictive Dialer on Jan 26, 2010 3:54 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...
In the case that is with adding nodes and the codes together does not seem to work fine with nhibernate. I tested this code and it worked fine there were some small issue which I troubleshooted. Thanks
Left by Predictive Dialer on Feb 02, 2010 9:07 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Your jewellery will be more pandora jewellery durable and more pandora jewellery beneficialpandora jewelryto your eyes if you care the following tips in our daily lives. Always wear the jewellery:, so they often wear pandora jewelleryand take off the jewellery. Actually, Some myopes are worried that wearing jewellery will deepen pandora jewellery the myopic degree pandora beads to see things squint when this worry is needless. You need to know wear pandora braceletsto correct vision, slow down pandora beads the development of pandora beads myopia. Ciliary muscle will be in a state of overstrain and If you often pandora beads wear off frequently, not wear, over time, make ciliaris. pandora rings, and eyes will be in a state of over-regulation causing spasm, which brings about degrees deepen.
Left by pandora beads on Feb 03, 2010 6:13 PM

# re: How to map a tree in NHibernate

Left by ugg boot on Feb 08, 2010 7:20 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Thanks for sharing. i really appreciate it that you shared with us such a informative post..
Administration Degree | Online Psychology degree | Clinical Psychology Degree | Social Science school | Online economics degree
Left by siomy on Feb 09, 2010 10:05 PM

# Mrs

Requesting Gravatar...
In the situation where you're adding nodes without a preset order, I can see this method working out well. best electric shaver
Left by janet on Feb 16, 2010 12:56 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Wonderful! As least now I know what does all that mean! Thank you very much for a good explanation and a detailed information. My colleagues are also interested in this topic, I will show them a copy of the material. All the best for you!
Left by evening dresses on Feb 21, 2010 2:22 AM

# re: How to map a tree in NHibernate

Left by gucci shoes on Feb 21, 2010 2:13 PM

# re: How to map a tree in NHibernate

Left by cheap picture frames on Feb 22, 2010 6:08 PM

# re: How to map a tree in NHibernate

Left by custom essay writing on Feb 22, 2010 10:03 PM

# Runescape Gold

Requesting Gravatar...
If you like usingRunescape Goldto play which needs users gold, you can borrowRunescape gp from friends, and you canrs gp. You have Runescape2 Gold , you can continue the game with rs2 gold. You must keepRunescape2 gp enough in the game.you can come here and spend a little money to boughtrs2 gp .
Left by Runescape Gold on Feb 24, 2010 1:36 PM

# discount ed hardy women long sleeve shirts sales online

Requesting Gravatar...
YS0225A5 If you think you are beaten, you are! If you think y dare noted hardy clothing, you don't! If you want to win but think you can't, It's almost a cinch you won't ed hardy hoodies! If you think you'll lose,you're lost! For out of the world we find.Success begins with a fellow's will,It's all in a ed hardy shirts state of mind! Life's battles don't always go.To the stronger and faster ed hardy coats man,But sooner or later the man who wins,Is the man who thinks he can! When You Belive http://www.edfashionclothes.com/,Many night we've prayed!With no proof anyone could hear!In our heart a hopeful moncler online store song,we barely understood!Now we are not afraid !Although we know there's much to fear!We were moving the moncler jackets mountian long,Before we knew we could!There can be miracles!
Left by discount mens moncler down coat on Feb 24, 2010 9:56 PM

# discount air jordan shoes 25 sales online

Requesting Gravatar...
YS0225A6 When you belive,Though hope is frail.It's hard to ll,Who knows what cheap prada shoes miracles,You can achieve,When you belive! Somehow you will,

You will when you belive new nike air max!And in this time of fear, When prayer so often proves in vain, Hope seems like the http://www.nikeaf1jordanshoes.com/summer birds. Too swiftly flown away, And now I am standing wholesale gucci shoes here.My heart's so full I can't explain.Seeking faith and speaking women's nike shox words I never thought I'd say, They don't always happen when you ask authentic air jordan shoes.And it's easy to give in to your fear. But when you're blinded by your pain!
Left by discount mens moncler down coat on Feb 24, 2010 10:04 PM

# discount Ugg Broome Boots in chestnut leather online sales

Requesting Gravatar...
YS0225A8 Before there was no reason in the world,As now there is!The moncler jackets course of water was my only course,My repetitions oceans' sough and swell ugg adirondack boots!My seasons pleasurable,Before there was no reason in the world,As now there i ugg broome boots!To measure time from sleep I rose to sleep,To measure space I pastured on surprise http://www.edhardy-buy.com/,O meadows of resemblances,I was the grove on whose mosaic floors,The moncler online seeds of otherwise were spent,My gods had many arms,I was the Caesar of unmarshaled grass ugg boots!Faustus in the branches,My first ambitions were my sorrows long!Before there was no reason in the world,As now there is!
Left by discount womens moncler jacket on Feb 24, 2010 10:59 PM

# discount air jordan shoes 23 sales online

Requesting Gravatar...
YS0225A7 when the sun hugs the moon, the sky clses her eyes.when the sun hug the moon the sea quiet her jordans shoes.when the sun hugs the moon,the forest stops her susurrus.when the sun hugs the nike sb dunk high,the desert hodlds her breathe.Thousands of years's waiting is only for this nike acg shoes moment.Never be disappointed.Never giv up.It hax been sucha long time.At nike air max 2003 this momentmeet each other in course of time.Do not cry,Moon.I guard you forever.Cause you are in my life,everyting has its meaning.The fascinating Diamond Ring,is the ring i give you,May it give you warm http://www.nikejordanshoes2sell.com/ threduce your tears.Do not cry,Sun,I will be there with you forever/Meeting you has given me precious memeory.The resplendent Baily Beads.is the gem i give you .May i give you cheap air jordan 22 shoes strength, shine in your morning.Meet soon and part soon.It makes peop;e retrospect in spite of lasting a few minutes.A long times waiting is coming.Don't know when the next meeting is .When the sun hugs the Moon. the Moon hugs the sun as well Hugging tightly,regian the lost nicety.
Left by discount nike air max shoes sale on Feb 24, 2010 11:03 PM

# discount christian louboutin sandals online sales

Requesting Gravatar...
YS0226A1 That your heart has been broken,Hear the words,I'm here, my child,;And know your christian louboutin uk angel has spoken.For even in the darkest hour,When all of discount louboutin shoes hope sems gone,They'll give you strength to live your life,And desire to go on.And if your faith in Heaven, Should ever fade away,They'll help renew your christian louboutin boots spirit, And help you find your way.Even though you're ever filled with doubt, About the christian louboutin pumps life you live,Know that they are there to give you All that they can give.For you see, the Father sent them,Because to Him, you mean so much,That He sent them just for you,my louboutin sale friend,And your life, they will touch.They will always be here,They will never leave your http://www.christianlouboutinshoestore.com/ side;And upon their strength and guidance,You always may rely.Take comfort in their guidance, Draw strength from up above,And know that their sweet presence,Is God's precious gift of love.
Left by cheap christian louboutin shoes on Feb 25, 2010 3:00 PM

# discount women's ugg elsey boots 5596 sales online

Requesting Gravatar...
YS0226A2 If were a boy again, I would practice perseverance more often, and never give up a thing because it was ugg australia boots or inconvenient. If we want light, we must conquer darkness. Perseverance can sometimes equal genius cheap ugg boots in its results. “There are only two creatures,” syas a proverb, “who can surmount the pyramids—the eagle and the snail.” If I were a uggs sale boy again, I would school myself into a habit of http://www.topsnowboots.com/ attention; I would let nothing come between me and the subject in hand. I would remember that a good skater never tries to skate in two ugg cardy boots directions at once. The habit of attention becomes part of our life, if we begain early enough. I often hear cheap gucci shoes grown up people say “ I could not fix my attention on the sermon or ugg coquette book, although I wished to do so” , and the reason is, the habit was not formed in youth.
Left by cheap ugg upside boots 5163 on Feb 25, 2010 3:01 PM

# discount Women's ugg adirondack boots II sales online

Requesting Gravatar...
YS0226A3 Hld fast to dreams.For if dreams die. Life is a broken-winged bird,That ugg australia boots can never fly.Hold fast to dreams. For when dreams go,Life is a barren ugg tall boots field, Frozen only with snow !You never know until you try; And you never try unless you really try ugg cardy boot. You give it your best shot; You do the best you can. And if you have done everything http://www.uggsnowbootsbest.com/! In your power,and still,The truth of the uggs argyle knit matter is! That you haven\'t failed at all.When you reach for your dreams,No matter what ugg boots they may be,You grow from the reaching;You learn from the trying;You win from the doing.
Left by cheap ugg classic cardy boots on Feb 25, 2010 3:05 PM

# discount reebok nfl jerseys online sales

Requesting Gravatar...
YS0226A4 A tre friend is someone who reaches for your hand and touches your cheap hockey jerseys heart.There's always going to be people that hurt you,so what you have to do is keep on trusting nfl jerseys and just be more careful about who sport jerseys you trust next time around.Make youself a better person and know who you are discount nba jerseys before you try and know someone else and expect them to know you mlb jerseys on sale.Remember:Whatever happens,happens for a reason.How many people actually have 8 true http://www.nfljerseymlb.com/friends Hardly anyone I know.But some of us have all right friends and good friends.
Left by cheap adiads nba jerseys sale on Feb 25, 2010 3:08 PM

# discount ugg sienna miller boots 5818 sales online

Requesting Gravatar...
YS0226A9 Unwaried still, lover by lover,They paddle in the cold,Companionable ugg australia shoes streams or climb the air;Their hearts have not grown old;ugg coquette Passion or conquest, wander where they will, Attend upon them still ugg adirondack boots. But now they drift on the still water, Mysterious, beautiful; Among what http://www.uggboots4buy.com/ rushes will they build, By what lake’s edge or pool,Delight men’s mbt shoes eyes when I awake some day.To find they have flown uggs classic cardy away?Before there was no reason in the world As now there is I was the bough bent easy by a ugg boots bird I was the vague blue-grazing flock The sleeping and invisible!
Left by cheap women's ugg elsey boots on Feb 25, 2010 3:12 PM

# discount mens air jordan shoes 13 online sales

Requesting Gravatar...
YS0226A10 Whe you are old and gray and full of sleep,And nodding by the moncler jackets fire, take down this book! And slowly read jordans sheoes , and dream of the soft look,Your eyes had once, and of their cheap nike shoes shadows deep;How many loved your moments of glad grace,And loved your beauty with nike air force 1 love false or true; But one man loved the pilgrim soul in you,And http://www.onestop-onlineshopping.com/ loved the sorrows of your changing face; And bending down beside the designer clothing glowing bars,Murmur, a little sadly, how love fled.And paced upon the mountains overhead discount air jordan shoes,And hid his face amid a crowd of stars.
Left by cheap nike air max 90 online on Feb 25, 2010 3:22 PM

# discount louis vuitton damier canvas handbags online sales

Requesting Gravatar...
YS0226A1 Surrounding you are angels,They are there to guide your path.If designer purses weaesskn overcomes you,They'll give you strength if you will ask. They are your protection.When discount designer bags on sale life seems too hard to bear,And though you feel alone at times, The louis vuitton 2009 angels ... they are there.Their faces may be hidden And their voices you might not hear,But they are ALWAYS with you,Through your laughter or your tears.http://www.handbags4buy.com/ They'll walk along beside you,They'll guide your leather handbags steps along the way, They'll comfort you and hold you,Protect you dior handbags night and day.They'll hold to your hand tightly ,They'll not ever let it go,And they'll gently lead you cheap designer handbagsforward,Taking each step very slow.For even as you slumber,They watch closely over you;They are there beside you. In each and every thing you do.
Left by cheap nike air max 90 online on Feb 25, 2010 3:26 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...

wedding dresses,wedding gowns,bride dresses,bridesmaids dresses,evening dresses,bridal gowns,flower girl dresses
Wedding Gowns
Formal Gowns
Cocktail Gowns
Find the wedding dress designer and wedding dress that's right for you! Browse dresses from
Bridesmaid Gowns
Evening Gowns
View our selection of exquisite, handmade gowns and dresses for your wedding
Wedding Dresses, Wedding Shoes and Wedding Accessories from wedding shop, the UK's finest collection of designer wedding dresses.
Use the wedding dress and
cheap wedding
wedding dresses
wedding shop
;lsa
Left by sbb on Feb 27, 2010 10:13 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Great blog!
Left by chondroitin MSM on Mar 02, 2010 8:22 AM

# re: How to map a tree in NHibernate

Requesting Gravatar...

wedding dresses,wedding gowns,bride dresses,bridesmaids dresses,evening dresses,bridal gowns,flower girl dresses
Wedding Gowns
Formal Gowns
Cocktail Gowns
Find the wedding dress designer and wedding dress that's right for you! Browse dresses from
Bridesmaid Gowns
Evening Gowns
View our selection of exquisite, handmade gowns and dresses for your wedding
Wedding Dresses, Wedding Shoes and Wedding Accessories from wedding shop, the UK's finest collection of designer wedding dresses.
Use the wedding dress and
cheap wedding
wedding dresses
wedding shop


;ll
Left by sbb on Mar 02, 2010 8:10 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
This is an excellent thought provoking post.
Left by ucvhost on Mar 06, 2010 2:42 AM

# ugg boots

Requesting Gravatar...
they are very good and useful!!!
ugg outlet
cheap uggs
nike shoes
wholesale watches
Left by ugg boots on Mar 07, 2010 5:24 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
It’s hard to find knowledgeable people on this topic, but you sound like you know what you’re talking about! Thanks Don’t stop writing, you’ve given me lots of good info! Youtube to MP4 Converter
Convert PDF to image
23fs
Left by powerpoint on Mar 08, 2010 2:22 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
54 It’s hard to find knowledgeable people on this topic, but you sound like you know what you’re talking about! Thanks Don’t stop writing, you’ve given me lots of good info! Youtube to MP4 Converter
Convert PDF to image .
Left by powerpoint on Mar 08, 2010 2:39 PM

# re: How to map a tree in NHibernate

Requesting Gravatar...
Whenever I hear friends talking about mbt, my feeling would always be a painful mixture of envy and

helplessness. As a matter of fact, I have long been craving about possessing a pair of MBT shoes. To a girl of low stature as me, a pair of mbt shoes could make me seem more slender or least won't be dwarfed by other girls. But its high price always

makes me feel hard to afford due to my restrained financial conditions.
But not long ago, a friend of mine sent me a pair of mbt shoes sale which thrilled me up for several days.

It's not until then that did I realize each penny for it is well paid. Indeed, it really deserves such a high price. I'm only regretting that I didn't

buy one earlier.
ot long ago, a friend oot long ago, a friend o
Left by ghd pink on Mar 09, 2010 3:40 PM

Your comment:

 (will show your gravatar)
 
Please add 5 and 3 and type the answer here: