3
votes

I have a bunch of C# classes which are inheriting a number of properties from an abstract base class. All of the types are mapped to a database model using Fluent NHibernate, and all of the property definitions use automatic getters and setters (the standard "get; set;" syntax). I recently found a need to provide a specific implementation for one of the accessor methods for a base type property on one of my derived types. So I created an explicit backing field for the base class property:

public abstract class BaseEntity : IBaseEntity
{
    protected bool active_field;

    ...

    public virtual bool active { get { return active_field; } set { active_field = value; } }

    ...

}

And then defined the specific getter logic for the "active" property in the derived type definition:

public override bool active
    {
        get { return active_field && (this.Expiration == null || this.Expiration < DateTime.Now); }
        set { active_field = value; }
    }

When I fire up the project, though, NHibernate throws an exception:

An exception of type 'System.InvalidOperationException' occurred in FluentNHibernate.dll but was not handled in user code. Additional information: Tried to add property 'active' when already added.

I'm guessing this has something to do with NHibernate needing to provide it's own override for the property definitions (hence why it requires the properties be declared virtual in the first place), but I'm not all that NHibernate savvy. That being the case, I'm happy to provide any other details, but don't really know what else is relevant. Is there an obvious reason why this can't work? If so, is there a simple workaround?

1
What if you make active non-virtual wrapper to another non-public virtual property? Will NHibernate fill non public property? - T.S.
So you have explicit mappings with ClassMap<T> or use Automapping? Also the override is flawed because when persisting, the active value can change even if active_field value did not change. better differentiate between IsActivated/IsEnabled (persisted) and IsActive - Firo
This is using automapping. I'm not sure what you mean in the latter part. All of the types which derive from BaseEntity are able to be "soft-deleted" by setting the active bit to 0. I recently added some BaseEntity types which have expiration dates, and I have an entire code base which is already explicitly checking the active field when examining data. My goal, of course, was to be able to view a BaseEntity type that has an Expiration property as inactive if the expiration had passed, without having to manually check it wherever I'm already checking the active field. Is that bad form? - Alec Hampton
T.S., I don't think NHibernate will populate non-public properties, as far as I know. - Alec Hampton

1 Answers

0
votes

I am not exactly sure about the origin of your problem, but, trying to answer your question:

  1. NHibernate needs all properties to be virtual to allow then to be lazy-loaded because it creates a proxy type of your entity type (which is an extension of your class). It needs them to be virtual so it can override them and inject a new behavior in it (fill them with the database value);
  2. You do can map non-public properties and fields, but you would have to do this explicitly, follows an example on how to do it with FluentNHibernate.

Mapping a private property or field:

public class EntityMap : ClassMap<Entity>
{
    Id(e => e.Id).GeneratedBy.Identity();
    Map(Reveal.Member<Entity>("PrivatePropertyName"));
}

Now a suggestion to try to solve your problem: you can hide the property on your extended class using the new keyword (the property still needs to be virtual).

public virtual new bool active
{
    get { return active_field && (this.Expiration == null || this.Expiration < DateTime.Now); }
    set { active_field = value; }
}