Search code examples
nhibernatefluentidentity-column

Temporarily turn off identity column with Fluent AutoMap?


I have begun to test Fluent NHibernate in C# I have a well normalized object structure with 20 related classes. I currently use Fluent 1.3 with NHibernate 3.2. So far I have managed to use the AutoMap feature which suits me fine, Very convenient!

BUT ... 3 of the tables are "enum tables" that need to have their records set with specific Id value. I tried to make manual mappings of these tables and let the rest be automapped. But when the manual table is created it fails because it references a table that is automapped (and not available for manual mapper?)

Is it possible to use AutoMapping but for some very few classes override identity creation on primary key? I tried to make a custom convention but without success.

public class OverrideIdentityGeneration : Attribute
{
}

public class ConventionIdentity : AttributePropertyConvention<OverrideIdentityGeneration>
{
    protected override void Apply(OverrideIdentityGeneration attribute, IPropertyInstance instance)
    {
        instance.Generated.Never();
    }
}

Is there some other way? It would be sad to be forced back to use manual mapping for all classes ....


Solution

  • I used the idea given by Fifo and extended it to use a custom attribute instead. To make code readable and avoid redundance when using similar idea in other conventions I added an extension method to check for custom attribute.

    This is the code I ended up with:

    /// <summary>
    /// Convention to instruct FluentNHIbernate to NOT generate identity columns
    /// when custom attribute is set.
    /// </summary>
    public class ConventionIdentity : IIdConvention
    {
        public void Apply(IIdentityInstance instance)
        {
            if(instance.CustomAttributeIsSet<NoIdentity>())
                instance.GeneratedBy.Assigned();
        }
    }
    
    /// <summary>
    /// Custom attribute definition.
    /// </summary>
    public class NoIdentity : Attribute
    {
    }
    
    /// <summary>
    /// Example on how to set attribute.
    /// </summary>
    public class Category
    {
        [NoIdentity]
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public static class IInspectorExtender
    {
        /// <summary>
        /// Extender to make convention usage easier.
        /// </summary> 
        public static T GetCustomAttribute<T>(this IInspector instance)
        {
            var memberInfos = instance.EntityType.GetMember(instance.StringIdentifierForModel);
            if(memberInfos.Length > 0)
            {
                var customAttributes = memberInfos[0].GetCustomAttributes(false);
                return customAttributes.OfType<T>().FirstOrDefault();
            }
            return default(T);
        }
    }