Search code examples
fluent-nhibernatecomponentsautomapping

How to rename a component column that is a foreign key?


We are using fluentnhibernate with automapping and we have a naming convention that all columns that are foreign keys, there column name will end with "Key". So we have a convention that looks like this:

public class ForeignKeyColumnNameConvention : IReferenceConvention
{
    public void Apply ( IManyToOneInstance instance )
    {
        // name the key field
        string propertyName = instance.Property.Name;

        instance.Column ( propertyName + "Key" );
    }
}

This works great until we created a component in which one of its values is a foreign key. By renaming the column here it overrides the default name given to the component column which includes the ComponentPrefix which is defined in the AutomappingConfiguration. Is there a way for me to get the ComponentPrefix in this convention? or is there some other way for me to get the column name for components with a property that is a foreign key to end in the word "Key"?


Solution

  • I Have figured out a way to do this using reflection to get to the underlying mapping of the IManyToOneInspector exposed by the IComponentInstance but was hoping there was a better way to do this?

    Here is some example code of how I achieved this:

    #region IConvention<IComponentInspector, IComponentInstance> Members 
        public void Apply(IComponentInstance instance) 
        { 
            foreach (var manyToOneInspector in instance.References) 
            { 
                var referenceName = string.Format("{0}_{1}_{2}{3}", instance.EntityType.Name, manyToOneInspector.Property.PropertyType.Name, _autoMappingConfiguration.GetComponentColumnPrefix(instance.Property), manyToOneInspector.Property.Name); 
                if(manyToOneInspector.Property.PropertyType.IsSubclassOf(typeof(LookupBase))) 
                { 
                    referenceName += "Lkp"; 
                } 
                manyToOneInspector.Index ( string.Format ( "{0}_FK_IDX", referenceName ) ); 
            } 
        } 
    #endregion 
    public static class ManyToOneInspectorExtensions 
    { 
        public static ManyToOneMapping GetMapping(this IManyToOneInspector manyToOneInspector) 
        { 
            var fieldInfo = manyToOneInspector.GetType ().GetField( "mapping", BindingFlags.NonPublic | BindingFlags.Instance ); 
            if (fieldInfo != null) 
            { 
                var manyToOneMapping = fieldInfo.GetValue( manyToOneInspector ) as ManyToOneMapping; 
                return manyToOneMapping; 
            } 
            return null; 
        } 
        public static void Index(this IManyToOneInspector manyToOneInspector, string indexName) 
        { 
            var mapping = manyToOneInspector.GetMapping (); 
            mapping.Index ( indexName ); 
        } 
        public static void Column(this IManyToOneInspector manyToOneInspector, string columnName) 
        { 
            var mapping = manyToOneInspector.GetMapping (); 
            mapping.Column ( columnName ); 
        } 
        public static void ForeignKey(this IManyToOneInspector manyToOneInspector, string foreignKeyName) 
        { 
            var mapping = manyToOneInspector.GetMapping(); 
            mapping.ForeignKey ( foreignKeyName ); 
        } 
    } 
    public static class ManyToOneMappingExtensions 
    { 
        public static void Index (this ManyToOneMapping manyToOneMapping, string indexName) 
        { 
            if (manyToOneMapping.Columns.First().IsSpecified("Index")) 
                return; 
            foreach (var column in manyToOneMapping.Columns) 
            { 
                column.Index = indexName; 
            } 
        } 
        public static void Column(this ManyToOneMapping manyToOneMapping, string columnName) 
        { 
            if (manyToOneMapping.Columns.UserDefined.Count() > 0) 
                return; 
            var originalColumn = manyToOneMapping.Columns.FirstOrDefault(); 
            var column = originalColumn == null ? new ColumnMapping() : originalColumn.Clone(); 
            column.Name = columnName; 
            manyToOneMapping.ClearColumns(); 
            manyToOneMapping.AddColumn(column); 
        } 
        public static void ForeignKey(this ManyToOneMapping manyToOneMapping, string foreignKeyName) 
        { 
            if (!manyToOneMapping.IsSpecified("ForeignKey")) 
                manyToOneMapping.ForeignKey = foreignKeyName; 
        } 
    }