Search code examples
oracle-databasenhibernatefluent-nhibernateautomapping

change the constraint name in fluentNhibernate auto mapping alteration


i'm using oracle with FluentNHibernate automapping with alterations & NHibernate the problem is how to specify the constraint name by overriding the mapping model??

the generated sql like this:

alter table FirstTable
    add constraint FK_VerLongIdentifierLongerThan30Characther
    foreign key (FirstTableID) 
    references SecondTable;

i need to change the "FK_VerLongIdentifierLongerThan30Characther" to smaller identifier by overriding the mapping model like this:

model.Override<SomeClass>(m =>
    {
        m.HasOne<SomeOtherClass>(c => c.SomeProperty).?????????;
        //or
        m.????????
    }
  )

Solution

  • Instead of doing an override for each class with this problem, what I have done is create a mapping convention which would truncate objects with surpass a 30-character naming scheme on foreign keys, has many and many to many relations:


    public class OracleIHasManyConvention : IHasManyConvention
    {
        public void Apply(IOneToManyCollectionInstance instance)
        {
            var keyName = string.Format(CultureInfo.InvariantCulture, "FK_{0}_{1}",
                                        instance.Member.Name,
                                        instance.EntityType.Name).Truncate(30);
    
            instance.Key.ForeignKey(keyName);
        }
    }
    

    public class OracleForeignKeyConvention : FluentNHibernate.Conventions.ForeignKeyConvention
    {
        protected override string GetKeyName(Member property, System.Type type)
        {
            var name = property == null
                       ? "Id_" + type.Name.ToUnderscoredNaming()
                       : "Id_" + property.Name.ToUnderscoredNaming();
    
            return name.Truncate(30);
        }
    }
    

    Then I would call these conventions like this:

    var cfg = Fluently.Configure()
                    .Database(SQLiteConfiguration.Standard.UsingFile("foobar.lite3"))
                    .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Product>()
                                                          .Where(a => a.Namespace == typeof (Product).Namespace)
                                                          .Conventions.Add<OracleIHasManyConvention>()
                                                          .Conventions.Add<OracleForeignKeyConvention>()
                                                          .Conventions.Add<OracleGeneralConvention>()
                                                          .Conventions.Add<CascadeAllConvention>()
                                       ));
    


    Here's the Truncate extension:

    public static class StringHelper
    {
        public static string Truncate(this string text, int endIndex)
        {
            if (text.Length > endIndex)
            {
                text = text.Substring(0, endIndex).TrimEnd('_');
            }
            return text;
        }
    }
    

    I hope this is useful in any way. :)