Mapping a read-only property with no setter using Fluent NHibernate

fluent-nhibernatenhibernate

I have a domain class that looks like this. I want NHibernate to save the current value of LastUpdate when inserting/updating so that I can use it in queries, but to ignore it when retrieving a Foo from the database and let the object itself recalculate the value when I actually access it.

public class Foo {
    public DateTime LastUpdate {
        get {
            /* Complex logic to determine last update by inspecting History */
            return value;
        }
    }
    public IEnumerable<History> History { get; set; }
    /* etc. */
}

My mapping for Foo looks like this:

public class FooMap : ClassMap<Foo> {
    Map(x => x.LastUpdate)
        .ReadOnly();
    HasMany(x => x.History);
    // etc...
}

I thought that ReadOnly() was what I wanted to accomplish this, but when I try to create a SessionFactory I get the following exception:

Error: FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
—> NHibernate.PropertyNotFoundException: Could not find a setter for property 'LastUpdate' in class 'Foo'.

The property doesn't have a setter because it shouldn't be set, only read from. Is ReadOnly() the correct thing to do here? If not, what?

(NHibernate v3.0b1, Fluent NHibernate v1.1)

Best Answer

ReadOnly instructs Fluent NHibernate to not look for changes on this property, this does not equate to a read-only property in compiler-world. Your property isn't read-only in NHibernate's eyes because you're expecting it to be populated from your database. What you need to do is tell NHibernate that it should access the value of that property through a private field with the same name (lowercased) as the property.

Map(x => x.LastUpdate)
  .Access.Field();

There are several alternatives to using Field, which one you use will depend on how you name your private fields.