Brian Chavez
Brian Chavez

Reputation: 8573

FluentNHibernate: Getting Column & Table Names After Mapping Conventions Are Applied

I am wondering if it is possible to find the run-time column name for a class/component that has been mapped with FluentNHibernate after all conventions have been applied.

For example, given the simple model:

 public class Address{ 
    public string Street {get; set;} 
    public string Zip {get; set;} 
 } 

 public class AddressMap : ComponentMap<Address>{
     Map( x => x.Street );
     Map( x => x.Zip );
 }

 public class PersonMap : ClassMap<Person> 
 { 
    public PersonMap(){ 

       Id( x => x.Id ); 
       Map( x=> x.Ssn );
       Map( x=> x.Name ); 

       Component( x => x.Address ) 
          .ColumnPrefix("ADDRESS_"); 
    } 
 }

public class ClassConvention : IClassConvention
{
    public void Apply( IClassInstance instance )
    {
        instance.Table( "tbl" + instance.EntityType.Name );
    }
}

Table Name: tblPerson

  Id     Name     Ssn         ADDRESS_Street     ADDRESS_Zip
 -----------------------------------------------------------
  1      Brian    11223344    123 Example St.    12345

What I'm looking for and what I am not sure how to do is the following:

var mappings = FluentNHibaernate.CompileMergeAndBuildAllMappings();

var zipCodeColumnName = mappings.FindMappedType<Address>().ColumnName(a => a.Zip)

zipCodeColumnName.ShouldBe("ADDRESS_Zip");
// Here I'm interested in the run-time & final column name with the
// prefix applied from the PersonMap class.

var personTableName = mappings.FindMappedType<Person>().TableName;
personTableName.ShouldBe("tblPerson");
// I'm interested in the final table name after the ClassConvention
// modified the table name.

Additional Clarification

Thanks for the help,
Brian

Upvotes: 4

Views: 4038

Answers (2)

Firo
Firo

Reputation: 30813

since component column names can be different for each application of the Component you have to know which property you want.

var config = Fluently.Configure()
    .DataBase(...)
    .Mappings(...)
    .BuildConfiguration();

var map = config.GetClassMapping(typeof(Person));

map.Table.Name.ShouldBe("tblPerson");
map.GetProperty("Address").IsComposite.ShouldBe(true);
((Component)map.GetProperty("Address").Value)
    .GetProperty("Zip").ColumnIterator.First()
    .Text.ShouldBe("ADDRESS_Zip");

Upvotes: 2

Brian Chavez
Brian Chavez

Reputation: 8573

    [Test]
    public void test4()
    {
        var ssnColumn = RuntimeNames
                           .ColumnName<Person>( x => x.Ssn );
        ssnColumn.ShouldEqual( "Ssn" );

        var addressColumn = RuntimeNames
                               .ColumnName<Person>( x => x.Address.Street );
        addressColumn.ShouldEqual( "ADDRESS_Street" );

        var personTableName = RuntimeNames
                                 .TableName<Person>();
        personTableName.ShouldEqual( "tblPerson" );
    }

public static class RuntimeNames
{
    private static Configuration cfg = Fluently.Configure()
        .Database( MsSqlConfiguration.MsSql2005 )
        .Mappings( m => m.FluentMappings
                            .AddFromAssemblyOf<PersonMap>()
                            .Conventions
                            .AddFromAssemblyOf<PersonMap>()
        ).BuildConfiguration();

    public static string ColumnName<T>( Expression<Func<T, object>> property )
        where T : class, new()
    {
        var accessor = FluentNHibernate.Utils.Reflection
            .ReflectionHelper.GetAccessor( property );

        var names = accessor.Name.Split('.');

        var classMapping = cfg.GetClassMapping( typeof( T ) );

        return WalkPropertyChain( classMapping.GetProperty(names.First()), 0, names );
    }

    private static string WalkPropertyChain(Property property, int index, string[] names)
    {
        if( property.IsComposite )
            return WalkPropertyChain( ((Component)property.Value).GetProperty( names[++index] ), index, names );

        return property.ColumnIterator.First().Text;
    }

    public static string TableName<T>() where T : class, new()
    {
        return cfg.GetClassMapping( typeof(T) )
            .Table.Name;
    }
}

Upvotes: 4

Related Questions