DCSIMG
Defining Acceptance criteria for mapping conventions in NHibernate - YsA.Net

Defining Acceptance criteria for mapping conventions in NHibernate

Posted Saturday, February 05, 2011 11:29 PM by ysa

Today I'm hosting a post from Leeran Yarhi, one of the developers in my team:

Hi guys,

I’m Leeran Yarhi, a developer in Yossi’s team.

Recently we had a problem while mapping one of our domain entities with Fluent NHibernate. We upgraded our app to use NHibernate 3 in conjunction with Fluent NHibernate 1.2. When we did that, some of our tests failed.

For example, let’s have a look at this entity:

public class User
{
    public virtual int Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string FullName { get; private set; }
}

And it’s mapping:

public class UserMap : ClassMap<User>
{
   public UserMap()
   {
       Id(x => x.Id);
       Map(x => x.FirstName);
       Map(x => x.LastName);
       Map(x => x.FullName).Formula("first_name || ' ' || last_name");
   }
}
 

As you can see, User has a property named FullName, which is actually a concatenation of FirstName and LastName. Of course I don’t really want to map this property to our Database. This is why I’m defining it a Formula, so that my Users table won’t really have a column for FullName

All good, but the problem starts when I try to use this PropertyConvention :

public class PropertyUnderscoreConvention : IPropertyConvention
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Column(Inflector.Underscore(instance.Property.Name));
    }
}

NHibernate will throw an exception because it’s trying to give a name to a column that doesn’t exist. The solution for this problem is to somehow define to my convention when it should apply, or in other words – Acceptance Criteria.

Fluent NHibernate gives us an API for defining the criteria that a mapping must satisfy for a convention to be applied to it. Exactly what I need.

The Convention class will now implement another interface: IAcceptanceCriteria<TInspector> , which contains the method Accept. This method defines the above criteria.

Let’s see some code, this is how my new convention looks like:

public interface IPropertyConventionAcceptance : IConventionAcceptance<IPropertyInspector>    
{
}     
 
public class PropertyConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Column(Inflector.Underscore(instance.Property.Name));
    }
 
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Formula == null);
    }
}
Now, my criteria will be applied only on properties that doesn’t have Formula, and all the mapping will work fine.

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above: