Ang3lFir3 – Life as a Code Poet

March 18, 2009

Fluent NHibernate new style mappings – powerful semantics

Filed under: Uncategorized, Fluent NHibernate, ORM, C#, NHibernate — Tags: , , , , , , — ang3lfir3 @ 5:56 pm

So today I updated to the latest build of Fluent NHibernate.  As any of you who might have done the same have discovered there are some breaking changes. I wasn’t sure I liked the new class based conventions at first, especially since it wasn’t clear at first how to tackle altering my mappings. Then it dawned on me how powerful the conventions would end up being while also promoting DRY.

as @jagregory said :

“brevity was sacrificed for power in this case.”

This can be seen in the example below which is a self referencing Parent Child relationship.

The description of the relationship is:

Categories can have one or none parents.

Categories can have many or no children.

The parent Category is always found in a property called “Parent”.

The children are always found in a property called “Children”.

Before

Original Mapping:

public class CategoryMap : ClassMap<Category>
{
  public CategoryMap()
  {
    Id(x => x.Id);
    Map(x => x.Name);
    References(x => x.Parent).TheColumnIs("parent_id").Cascade.All();
    HasManyToMany(x => x.Products).Inverse();
    HasMany(x => x.Children).WithKeyColumn("parent_id").Cascade.All().Inverse();
  }
}

**Note:  These aren’t exactly “Conventions” but it turned out that ‘WithKeyColumn’ got dropped and I had to look for a better way. The new style conventions offered that even over older convention styles.

After

The new style Convention Mappings :

The Convention classes below create a convention that reads like:

“For a HasMany when the child type matches the type of the root and the name of the property is ‘Children’  then use the column ‘parent_id’ as the KeyColumn. For a Reference when the child type matches the type of the root and the name of the property is ‘Parent’ then set its reference ColumnName to ‘parent_id’ “

public class SelfReferencingHasManyConvention : IHasManyConvention
{
  public bool Accept(IOneToManyPart target)
  {
     return target.Member.ReflectedType == target.EntityType && target.Member.Name == "Children";
  }

  public void Apply(IOneToManyPart target)
  {
     target.KeyColumnNames.Clear();
     target.KeyColumnNames.Add("parent_id");
  }
}
public class SelfReferencingReferenceConvention : IReferenceConvention
{
  public bool Accept(IManyToOnePart target)
  {
    return target.Property.ReflectedType == target.EntityType && target.Property.Name == "Parent";
  }

  public void Apply(IManyToOnePart target)
  {
     target.ColumnName("parent_id");
  }
}

The Mapping after the convention :

Clean and clear, the conventions themselves are not cluttering the Mapping. More importantly the conventions help me stay DRY.

public class CategoryMap : ClassMap<Category>
{
  public CategoryMap()
  {
    Id(x => x.Id);
    Map(x => x.Name);
    References(x => x.Parent).Cascade.All();
    HasManyToMany(x => x.Products).Inverse();
    HasMany(x => x.Children).Cascade.All().Inverse();
  }
}

Adding Mappings to my Persistence Model

You can see that adding the conventions was pretty easy and straight forward. This applies to the fact that I am using the PersistenceModel approach.

public class DataModel : PersistenceModel
{
  public DataModel()
  {
     AddMapping(new ProductMap());
     AddMapping(new CategoryMap());
     ConventionFinder.AddFromAssemblyOf<DataModel>();
   }
}

kick it on DotNetKicks.com

About these ads

4 Comments »

  1. Great post! I’ve been trying to test this code out though, and I’m getting an error in my tests:

    System.ApplicationException: Actual count does not equal expected count.

    Here’s my test:

    [TestMethod]
    public void Mapping_Category_IsValid()
    {
    new PersistenceSpecification(Session)
    .CheckProperty(x => x.Id, 3)
    .CheckProperty(x => x.Description, “Cat Desc Here”)
    .CheckProperty(x => x.Name, “Cat Name Here”)
    .CheckReference(x => x.ParentCategory, GetSubjectCategory())
    .CheckList(x => x.SubCategories, new List(new[] { GetChildCategory() }))
    .VerifyTheMappings();
    }

    Any ideas? Did you come across this issue? Thanks!

    Comment by Chris — April 23, 2009 @ 11:58 pm

    • Chris,
      Are you using the code from the post verbatum? If you are it’s important to note that it assumes the names of the properties will be “Parent” and “Children”.

      I don’t use the PersistanceSpecification to test my mappings as I manage that from the BDD style tests I wrote while working on the app this belonged in. Feel free to email me at ang3lfir3 AT google’s mail service dot com with more info and a more complete sample and I’ll be happy to help.

      Thanks I am always happy to help.

      Comment by ang3lfir3 — April 25, 2009 @ 7:58 pm

  2. Worked absolutely perfectly.

    SharpArchitecture’s existing ReferenceConvention and HasManyConvention were overriding my very un-DRY fluent mappings, and adding these conventions did the trick and really cleaned up my mappings.

    Comment by Nick — October 7, 2009 @ 9:42 am

  3. certainly like your website but you need to take a look at
    the spelling on several of your posts. Many of them are rife
    with spelling problems and I to find it very troublesome to inform the reality on the
    other hand I will surely come back again.

    Comment by Alix N. Ellsbury — September 28, 2014 @ 4:01 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Theme: Silver is the New Black. Get a free blog at WordPress.com

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: