A fluent interface to NHibernate - Part 3 - Mapping Relations

This is the third post in a series of articles where I want to analyze and describe the new upcoming mapping interface providing a fluent interface to NHibernate for the mapping of a domain model to the underlying database. The other posts are

You can get the source code of the solution accompanying this post here.

In the time between my last post and today a lot has happened to the mapping framework. The contributors are busily improving the source and are also very responsive to my questions and remarks.

In this post I want to focus on how one can map various relations between entities and value objects of a domain model.

Scenario 3

Domain Model

Let's have a look at the following simplified model

image

I have a Blog which has an author of type Person. Each Blog can have many Posts. To each Post readers can give feedback in the form of Comments. Comments are considered value objects in this model, that is they have no identity and are immutable (a reader cannot edit its comment after it has been published...). All other elements are true entities. If I consider the Blog to be the root object then the relation between Blog and Person is of type many-to-one (a person can be the owner of more than one blog). On the other hand the relation between Blog and Post is of type one-to-many. The parent and the children are both entities.

A special case (as we will see) is the relation between Post and Comment (since Comment is a value object). It is also of type one-to-many but this time the parent is an entity and the children are value objects.

Mapping

How can we map this? Well, let's start with the easy one. In this simplified model the Person class has no external dependencies and is thus easy to map

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Id(x => x.Id);
        Map(x => x.FirstName);
        Map(x => x.LastName);
    }
}

The Comment class has also no external dependencies. I want to treat the Comment as a value Object. So I have to map it as follows

public class PostMap : ClassMap<Post>
{
    public PostMap()
    {
        Id(x => x.Id);
        Map(x => x.Title);
        Map(x => x.Body);
        Map(x => x.PublicationDate);
        HasManyComponent<Comment>(x => x.Comments,
                                  c =>
                                      {
                                          c.Map(x => x.Text);
                                          c.Map(x => x.AuthorEmail);
                                          c.Map(x => x.CreationDate);
                                      }).AsSet();
    }
}

I had to implement the method HasManyComponent by myself since it was missing in the actual trunk of the framework. That is, it was not possible to map a collection of value objects. But it has not been that hard since the source base is really nice. My changes will probably be integrated into the framework soon. The official contributors to the project are VERY responsive and do their best to fix bugs and/or implement missing features. Keep on rolling guys! IMHO we will see soon a high adoption rate of this new framework in the NHibernate community if the development pace stay at this high rate.

I don't want to show the implementation details of the method mentioned above in this post since it is off-topic and since it will soon be incorporated into the framework anyway. Eventually the name of the method will change though...

Finally we can map the Blog class which is now easy

public class BlogMap : ClassMap<Blog>
{
    public BlogMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        References(x => x.Author);
        HasMany<Post>(x => x.Posts).AsSet();
    }
}

Note that we map the many-to-one relation between Blog and Person with the aid of the References method. Note further that we map the collection of Posts with the HasMany method. Since by default this method maps to a "bag" we have to further specify that we want to map with a "set" (--> see my post on collection mapping for the various types of collections).

The XML generated by the above mapping class is shown below. Now you can ask yourself which way of mapping your entities you prefer...

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" 
                   assembly="FluentMapping.Domain" 
                   namespace="FluentMapping.Domain.Scenario3">
  <class name="Post" table="[Post]" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="Int64">
      <generator class="identity" />
    </id>
    <property name="PublicationDate" column="PublicationDate" type="DateTime">
      <column name="PublicationDate" />
    </property>
    <property name="Body" column="Body" length="100" type="String">
      <column name="Body" />
    </property>
    <property name="Title" column="Title" length="100" type="String">
      <column name="Title" />
    </property>
    <set name="Comments" cascade="none">
      <key column="Post_id" />
      <composite-element class="FluentMapping.Domain.Scenario3.Comment, 
                                FluentMapping.Domain, Version=1.0.0.0, 
                                Culture=neutral, PublicKeyToken=null">
        <property name="CreationDate" column="CreationDate" type="DateTime">
          <column name="CreationDate" />
        </property>
        <property name="AuthorEmail" column="AuthorEmail" length="100" type="String">
          <column name="AuthorEmail" />
        </property>
        <property name="Text" column="Text" length="100" type="String">
          <column name="Text" />
        </property>
      </composite-element>
    </set>
  </class>
</hibernate-mapping>

Ok I admit, when hand crafting the XML we can skip some of the elements, but still...

Testing

All tests use the base class FixtureBase which I have introduced in my first post about the mapping framework. In the mean time the SessionSource class of the framework has been re-factored such as that it now works for our scenarios and I don't have to use my own implementation any more. For completeness I present here the updated source once again

public class FixtureBase
{
    protected SessionSource SessionSource { get; set; }
    protected ISession Session { get; private set; }
 
    [SetUp]
    public void SetupContext()
    {
        Before_each_test();
    }
 
    [TearDown]
    public void TearDownContext()
    {
        After_each_test();
    }
 
    protected virtual void Before_each_test()
    {
        SessionSource = new SessionSource(new TestModel());
        Session = SessionSource.CreateSession();
        SessionSource.BuildSchema(Session);
        CreateInitialData(Session);
        Session.Flush();
        Session.Clear();
    }
 
    protected virtual void After_each_test()
    {
        Session.Close();
        Session.Dispose();
    }
 
    protected virtual void CreateInitialData(ISession session)
    {
    }
}

The only two lines that have changed are printed in bold.

Now let's test whether we can create a blog and add posts to it. Let's start with the former. I define a base class for all my further blog related tests as

public class Blog_Fixture : FixtureBase
{
    protected Person author;
 
    protected override void CreateInitialData(ISession session)
    {
        base.CreateInitialData(session);
        author = new Person {FirstName = "Gabriel", LastName = "Schenker"};
        session.Save(author);
    }
}

In the CreateInitialData method I create an author object since every blog has to have an author. I save this author object to the database. To make the author available to all child test classes I have declared it as a protected filed. Now to the test which tries to create a new blog and verifies that it has be written correctly and completely to the database

[TestFixture]
public class When_no_blog_exists : Blog_Fixture
{
    [Test]
    public void Can_add_new_blog()
    {
        var blog = new Blog {Name = "Gabriel's Blog", Author = author};
        Session.Save(blog);
        Session.Flush();
        Session.Clear();
 
        var fromDb = Session.Get<Blog>(blog.Id);
 
        fromDb.ShouldNotBeNull();
        fromDb.ShouldNotBeTheSameAs(blog);
        fromDb.Id.ShouldEqual(blog.Id);
        fromDb.Name.ShouldEqual(blog.Name);
        fromDb.Author.ShouldNotBeNull();
        fromDb.Author.Id.ShouldEqual(blog.Author.Id);
    }
}

Note that I have inherited this test class from the previously implemented Blog_Fixture class. In the test method I first create a new blog instance. Then I save it to the database. I then flush and clear the session instance to guarantee that all the object(s) in NHibernate's session cache are written to the DB and that the cache is cleared afterwards such as that when a read operation is invoked the respective object is really retrieved from the database.

If you wonder where all these ShouldXXX methods in the second part of the test come from then wonder no longer. These are extension methods which I have implemented. They make all the asserts that you normally would do with the aid on NUnit's Assert class. But like this the code is way more readable, isn't it? If you wonder how these methods are implemented then please have a look into the source code of the solution accompanying this post. Search for the class SpecificationExtensions.

When running this test it succeeds!

But we have seen in the past that the framework offers us some help to reduce the size of our test methods. So let's revisit the test and leverage the framework.

[Test]
public void Can_add_new_blog_revisited()
{
    new PersistenceSpecification<Blog>(Session)
        .CheckProperty(x => x.Name, "Gabriel's Blog")
        .CheckProperty(x => x.Author, author);
}
Yeah, much shorter! That's what I call wrist friendly... Of course when run also this test succeeds.

Second we want to try to add a post to an already existing blog. I have the following code for that

 
[TestFixture]
public class When_a_blog_exists : Blog_Fixture
{
    private Blog blog;
 
    protected override void CreateInitialData(ISession session)
    {
        base.CreateInitialData(session);
        blog = new Blog {Name = "Gabriel's Blog", Author = author};
        session.Save(blog);
    }
 
    [Test]
    public void Can_add_post_to_blog()
    {
        var post = new Post
                    {
                        Title = "First Post",
                        Body = "Just a test",
                        PublicationDate = DateTime.Today
                    };
        blog.Posts.Add(post);
        Session.Update(blog);
 
        Session.Flush();
        Session.Clear();
 
        var fromDb = Session.Get<Blog>(blog.Id);
 
        fromDb.Posts.Count.ShouldEqual(1);
        fromDb.Posts.First().Id.ShouldEqual(post.Id);
    }
}

In the CreateInitialData I setup my context which in this case is: I have a blog in the database. In the test method I take this existing blog instance and add a new post to it. I then tell the session to update the blog. As usual I flush and clear the session before I assert that the operation was indeed successful.

Now I reload the blog from the database and test whether it has one post as expected and whether it's the post we have added to the blog (it suffices to test the post's id). Note that the method First() applied to the Posts collection of the blog (on the last line of the test) is also an extension method. This extension method just returns the first element of any collection of objects implementing IEnumerable<T> onto which it is applied.

Again when we run the test it is successful.

We want to leverage the framework once more and thus I revisit the test

[Test]
public void Can_add_post_to_blog_revisited()
{
    var posts = new[]
                    {
                        new Post {
                                    Title = "First Post",
                                    Body = "Just a test",
                                    PublicationDate = DateTime.Today
                                 },
                        new Post {
                                    Title = "Second Post",
                                    Body = "Just another test",
                                    PublicationDate = DateTime.Today.AddDays(-1)
                                 },
                    };
 
    new PersistenceSpecification<Blog>(Session)
        .CheckProperty(x => x.Name, "Gabriel's Blog")
        .CheckProperty(x => x.Author, author)
        .CheckList(x=>x.Posts, posts);
}

Once again I use our friend the PersistenceSpecification class. This time I use it's method CheckList to test the Posts collection of the blog instance. This method expects a collection of Post objects which I have defined in the first part of this test. Here I have defined two posts in the list but also a single one would suffice for the test.

Let me resume: to completely test the mapping of the Blog class I need four lines of code! Nice.

The last thing we have left to test is whether we can add comments to our posts. First I setup my context; that is I have a blog with one post. I also prepare a comment which I can then later on add to the post.

[TestFixture]
public class When_a_blog_with_a_post_exists : Blog_Fixture
{
    private Blog blog;
    private Post post;
    private Comment comment;
 
    protected override void CreateInitialData(ISession session)
    {
        base.CreateInitialData(session);
        blog = new Blog { Name = "Gabriel's Blog", Author = author };
        post = new Post
                   {
                       Title = "First Post",
                       Body = "Just a test",
                       PublicationDate = DateTime.Today
                   };
        blog.Posts.Add(post);
        session.Save(blog);
 
        comment = new Comment("This is my comment", DateTime.Today, "someone@gmail.com");
    }
}

Once my context is set up writing the test is easy. I read the post from the database, add the prepared comment to it and then flush and clear the session (note that the session automatically realizes that the post is dirty and that an update must be made to the database). The I re-read the post from the database and verify that indeed one comment was added and that it is the comment which I expect (by comparing it's Id).

[Test]
public void Can_add_comment_to_post()
{
    var thePost = Session.Get<Post>(post.Id);
    thePost.Comments.Add(comment);
    
    Session.Flush();
    Session.Clear();
 
    var fromDb = Session.Get<Post>(post.Id);
    fromDb.Comments.Count.ShouldEqual(1);
    fromDb.Comments.First().Equals(comment);
}

And again the test succeeds. Unfortunately we cannot leverage the framework this time since the CheckList method of the PersistenceSpecification class does not yet work for collections of value objects. But I'm sure this will be fixed soon. The test would be like this

[Test][Ignore(".CheckList is not yet working")]
public void Can_add_comment_to_post_revisited()
{
    new PersistenceSpecification<Post>(Session)
        .CheckProperty(x => x.Title, "Some title")
        .CheckProperty(x => x.Body, "Some text")
        .CheckProperty(x => x.PublicationDate, DateTime.Today)
        .CheckList(x => x.Comments, new[] {comment});
}

Source Code

You can get the source code of the solution accompanying this post here.

Summary

In this post I have shown you that the mapping framework is indeed ready for mapping more advanced scenarios. I have shown you how to map one-to-many relations where either the children are entities or the children are value objects. I also have shown how to map many-to-one relations.

Print | posted on Friday, August 15, 2008 1:36 AM

Comments on this post

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Could you please post on using Fluent NHibernate for class hierarchies (inheritance)?
Left by Praveen Angyan on Oct 19, 2008 8:53 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Hi Gabriel,

I'm requested a password & username for this svn project. Could you check the settings?

Kr,
Tom
Left by Tom on Oct 20, 2008 8:30 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
@Tom: use http instead of https (my fault, sorry)
Left by nhibernate on Oct 21, 2008 7:17 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
I updated the wrong links to the code repository!
Left by nhibernate on Oct 21, 2008 7:24 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
thanks
Left by Tom on Oct 22, 2008 12:31 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Hi Gabriel

Love your posts! I'm sure you've got some thoughts on mapping the domain for inheritance (in general) and using fluent hibernate to do that. But I don't see them..

Have you posted on this before? Any links to other postings you agree with?

Thx,
Berryl

Left by Berryl Hesh on Mar 02, 2009 11:16 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
I begun replacing the hbm files with fluent C# code mapping files. I also begun writing unit test to test the mappings. My issue is with IDictionary support and ISet support in PersistenceSpecification class. From what I saw there is only support for CheckProperty, CheckList and CheckReference. Is there a way to check Iset and dictionaries?

thanks,
Marius
Left by marius on Jul 07, 2009 2:33 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
thanks for your valuable suggestion to this site.i really appreciate your work to this site.
Left by Boni für Black Jack on Oct 30, 2009 8:01 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
If you wonder how these methods are implemented then please have a look into the source code of the solution accompanying this post. Search for the class SpecificationExtensions.
Left by Orkut Greetings on Nov 16, 2009 10:53 AM

# What if the 1<->many mapping uses .inverse?

Requesting Gravatar...
Hi!
I'm trying a very similar example with a one-to-many entity mapping similar to Blog<-> Posts.
However, I'd like to use the 'Inverse' attribute on it (one reason is to avoid ever having 'posts' in the DB that have a NULL in their BlogID column (even if temporary).
For this to work, the Blog class has an AddPosts(...) method that takes care to set up both ends of the mapping.
The problem is, the PersistenceSpecification instance doesn't offer access to the actual blog instance, so I can't call the blog.AddPosts(...) method, resulting in "System.ApplicationException: Actual count does not equal expected count" - because the BlogID value is never set for the Post objects.
If I remove the 'Inverse' attribute on the mapping, the BlogID values are updated as expected, and the test passes.
Any idea how to get this to work without ditching the 'Inverse' attribute ?
Left by Cristian on Nov 30, 2009 9:31 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Left by free insurance quotes on Dec 06, 2009 8:06 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
I'm runnig for cover. I'm very excited and looking forward for the complete API of the FluentInterface and the LINQ stuff seeing the NH bomb hitting the ground!
Left by play craps on Dec 11, 2009 6:19 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
My issue is with IDictionary support and ISet support in PersistenceSpecification class. From what I saw there is only support for CheckProperty, CheckList and CheckReference. Is there a way to check Iset and dictionaries?
Left by pandora jewelry on Dec 24, 2009 11:58 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Fluent NHibernate is so extensible, I can easily create a convention to use the Attributes. Then all I have to do is add the convention to my Fluent NHibernate AutoMapper instance and the properties with the attributes are just taken care of.
Left by casino online ratings on Jan 22, 2010 4:34 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
This is a cool screen idea ! It is very interesting indeed.Thank you for your info.i love to read all info.This article gives the light in which we can observe the reality.
Left by Apex Professionals on Feb 01, 2010 12:07 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
I've already bookmark this article and will surely refer this to all my close friends.
Left by 25th Wedding Anniversary on Feb 03, 2010 5:51 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Nice information and I'm interested. BlogEngine is one of the best blogs around.. thanks for this nice article...
Left by Debt consolidation on Feb 03, 2010 11:53 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Very useful informations about these subject. Great info.I like all your post.Interesting article..
Left by playedonline on Feb 07, 2010 10:46 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Really appreciate this post. It’s hard to sort the good from the bad sometimes, but I think you’ve nailed it!
Left by link wheel on Feb 09, 2010 9:26 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Great info.I like all your post.I will keep visiting this blog very often.It is good to see you verbalise from the heart and your clarity on this important subject can be easily observed..We Provide you the best Online SEO Services with high quality.
Left by Online SEO services on Feb 17, 2010 5:38 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
really good article cheers
Left by watches uk on Feb 18, 2010 2:00 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
It’s nice to read a sane commentary for once.We are offering premium link wheel services with unique content and wheel promotion to social bookmarking sites.We are different from other link wheel service providers..
Left by Link wheel service on Feb 19, 2010 12:31 AM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
Nice Post!. I've been a "creeper on your blog for quite a while. You make some very good points in this one.Just wanted to say keep up the good work!
Left by Link building campaign on Feb 21, 2010 8:47 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

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

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Left by custom essay writing on Feb 22, 2010 9:48 PM

# Bounty Bay gold

Requesting Gravatar...
Do you knowBounty Bay gold?if you play the online game,you will knowBBO Goldis the game gold. In the game,if you had moreBounty Bay Online Gold,you will had a tall level. But if you wantBounty Bay Coin,you can come here and spend a little money to boughtBounty Bay online Coin .Quickly come here.
Left by Bounty Bay gold on Feb 24, 2010 1:40 PM

# discount ed hardy women long sleeve shirts sales online

Requesting Gravatar...
YS0225A5 If you think you are beaten, you are! If you think you 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 worl 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:57 PM

# discount air jordan shoes 25 sales online

Requesting Gravatar...
YS0225A6 Whe you belive,Though hope is frail.It's hard to kill,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 nreason 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 is 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:45 PM

# discount air jordan shoes 23 sales online

Requesting Gravatar...
YS0225A7 when the sn 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 give 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 10:47 PM

# discount ed hardy women long sleeve shirts sales online

Requesting Gravatar...
YS0225A5 If you think you are beaten, you are! If you think you 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 wi 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 10:52 PM

# discount christian louboutin sandals online sales

Requesting Gravatar...
YS0226A1 That your heart has been broken,Hear the word,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 seems 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:31 PM

# discount women's ugg elsey boots 5596 sales online

Requesting Gravatar...
YS0226A2 If I were a boy again, I would pracice 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:38 PM

# discount Women's ugg adirondack boots II sales online

Requesting Gravatar...
YS0226A3 Hold fast to dreams.For if dreams e. 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:46 PM

# discount reebok nfl jerseys online sales

Requesting Gravatar...
YS0226A4 A true friend meone 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:52 PM

# discount ugg sienna miller boots 5818 sales online

Requesting Gravatar...
YS0226A9 Unwearied still, lover by lover,They pale 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:55 PM

# discount mens air jordan shoes 13 online sales

Requesting Gravatar...
YS0226A10 When you are old and gray and full of sleep,And ng 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 4:01 PM

# discount louis vuitton damier canvas handbags online sales

Requesting Gravatar...
YS0226A11 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. T 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 4:08 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

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
wwwww
Left by sbb on Feb 27, 2010 10:14 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Left by abercrombie on Feb 28, 2010 6:34 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

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


kkkk
Left by sbb on Mar 02, 2010 8:12 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Left by links of london on Mar 03, 2010 7:49 PM

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
thanks for your valuable suggestion to this site.
Left by ucvhost on Mar 06, 2010 2:28 AM

# ugg boots

Requesting Gravatar...


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

# re: A fluent interface to NHibernate - Part 3 - Mapping Relations

Requesting Gravatar...
vw 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:23 PM

Your comment:

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