FluentNHibernate Component.ColumnPrefix not being

2019-07-03 00:24发布

问题:

I recently upgraded FluentNHibernate from v1.1.0.685 to v1.2.0.712 (latest) for NHibernate 2.1.

My issue appears to be with classes that use the Component().ColumnPrefix() mapping.

For example,

 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.Name ); 

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

Person Table

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

Behavior in FNH v1.1.0.685

The "ADDRESS_" prefix is correctly applied to the properties of the Address component.

Behavior in FNH v1.2.0.712 (latest)

The "ADDRESS_" prefix is no longer applied to the properties of the Address component. NHiberante generates "Street" and "Zip" columns which are not named in table above.


I'd appreciate if anyone has any insight. I'm beginning to think this might be a bug.

Thanks,
Brian

回答1:

@Brian,

I hit the exact roadblock a few weeks ago. I'm using automappings and got around it by creating a Component Property Convention:

Public Class ComponentPropertyConvention
    Implements IPropertyConvention, IPropertyConventionAcceptance

    Public Sub Accept(ByVal criteria As IAcceptanceCriteria(Of IPropertyInspector)) Implements IConventionAcceptance(Of IPropertyInspector).Accept
       criteria.Expect(Function(inspector) inspector.EntityType.Namespace.EndsWith("Components"))
    End Sub

    Public Sub Apply(ByVal instance As IPropertyInstance) Implements IConvention(Of IPropertyInspector, IPropertyInstance).Apply
        instance.Column(String.Format("{0}_{1}", New String() {instance.EntityType.Name.ToLower(), instance.Property.Name.Dbize()}))
    End Sub

End Class

There's probably a wealth of ways to implement your acceptance criteria so don't follow mine if it doesnt suit...

Cheers



回答2:

After investigating the unit tests in the source code; it appears that, in my case, my conventions were being applied differently between FNH v1.1 and FNH v1.2.

I think this is what happened:

  1. My AddressMap : ComponentMap<Address> would get executed (no problem here).

  2. My PersonMap : ClassMap<Person> would map a component using:

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

    from Step 1.

  3. My FNH MyPropertyConvention would call:

    public class MyPropertyConvention : IPropertyConvention
    {
        public void Apply( IPropertyInstance instance )
        {
            instance.Column( instance.Name ); //this call is destructive
                                              //to ColumnPrefix() in FNH v1.2
        }
    }
    

It appears:

  • in FNH v1.1, Step 3 is not destructive to the column prefix when calling instance.Column().

  • in FNH v1.2, Step 3 is destructive to any ColumnPrefix() previously set and over-writes the entire column name (including the prefix).

So, I cleaned up my conventions for FNH 1.2 using IPropertyConventionAcceptance being careful about my calls to instance.Column(instance.Name) [now that calls are destructive to column prefixes].

Thanks for everyone's help,
Brian



回答3:

You need to create a ComponentMap<Address> class in order for the ColumnPrefix to be applied.

See here: http://wiki.fluentnhibernate.org/Fluent_mapping#ComponentMap.3CT.3E