Twitter Feed Popout byInfofru

OverrideThis.com

Adventures in .NET Software Craftsmanship!

FluentNHibernate1.1 RTW and ReadOnly Properties

As detailed in the FluentNHibernate website the 1.1 RTW was released last month!  The main purpose of the release was to get everybody off the trunk and have the latest version of FluentNHibernate target the latest NHibernate build 2.1.2GA.   Additionally, the release included a lot of new functionality and bug fixes that have been added by community members.  At first glance there didn’t seem to be any changes that would break any existing applications, but as always with these type of things I managed to find a scenario where an existing project simply collapsed because of decisions made on the original design.

 

Trouble Scenario

While using 1.0RTM and the default auto mapping functionality, a class like the Budget class in the following snippet would result in the Id being mapped as the identifier, the Amount being mapped as a property and the AmountFormatted property would be ignored as it would be identified as a read only property. This behavior changes significantly in the 1.1RTW build where the default behavior is to map the AmountFormatted property producing a nasty error that stresses that no setter was found for this property, if indeed your intent is to map and persist the information in this read only property then you would have to define an access strategy for a backing field.

 

public class Budget {
    public virtual int Id { get; protected set; }
    public virtual decimal Amount { get; set; }
    public virtual string AmountFormatted {
        get { return string.Format("{0:c}", this.Amount); }
    }
}

 

Solution
If you do not intent to persist the information in that read only property, one possible solution is to specify IAutoMappingOverride<T> classes for all entities that are being mapped in your system and manually specify each read only properties to be ignored.  Needless to say that this is not the preferred migration path for a large application where we relied on the original auto mapping behavior and now have 30 or 40 entities that we would need to build specific overrides for.  The more elegant solution is to use a new feature in 1.1RTW, the new AutoMappingConfiguration that allows you to define rules for types that are to be mapped and members of those types.  So adding the following CustomAutoMappingConfiguration solved all my problems.

 

public class CustomMappingConfiguration : DefaultAutomappingConfiguration {
    
    public override bool ShouldMap(Member member) {
        return member.CanWrite && member.IsProperty && base.ShouldMap(member);
    }

    public override bool ShouldMap(System.Type type) {
        return typeof(Budget).Namespace == type.Namespace;
    }
}

 

Hopefully, if you find yourself doing a similar migration this will help get you on your way.