Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does AutoMapping from Fluent's NHibernate ignore an enum type?

I have the following enumeration type:

public enum EnumType
{
    E1,
    E2
}

used in the following class:

public class X
{
    public virtual int? Id { get; set; }

    public virtual EnumType EnumProperty { get; set; }

    public virtual string S { get; set; }
}

I want to persist instances of this type in a database using NHibernate. And to avoid writing boilerplate code, I'm trying to use auto mapping feature as follows:

private ISessionFactory CreateSessionFactory()
{
    var mappings = AutoMap
        .AssemblyOf<Domain.X>(new MyAutoMappingConfiguration());

    this.NHibernateConfiguration = Fluently
        .Configure()
        .Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2012.ConnectionString(
                b => b.FromConnectionStringWithKey("x")))
        .Mappings(m => m.AutoMappings.Add(mappings))
        .BuildConfiguration();

    return this.NHibernateConfiguration.BuildSessionFactory();
}

where MyAutoMappingConfiguration looks like this:

public class MyAutoMappingConfiguration: FluentNHibernate.Automapping.DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        return type.Namespace == "Domain";
    }

    public override bool IsComponent(Type type)
    {
        return type.Name == "EnumType";
    }
}

When I use the schema generated from this configuration to create the database:

new SchemaExport(this.sessionProvider.NHibernateConfiguration)
    .Execute(true, true, false);

the following script is being generated and executed:

if exists (select * from dbo.sysobjects where id = object_id(N'[X]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [X]

create table [X] (
    Id INT not null,
   S NVARCHAR(255) null,
   primary key (Id)
)

Why is the property EnumProperty ignored?

When I add an explicit mapping for X, or (what seems equivalent) an override for auto-mapping like this:

var mappings = AutoMap
    .AssemblyOf<Domain.X>(new MyAutoMappingConfiguration())
    .Override<Domain.X>(m =>
    {
        m.Table("X");
        m.Id(x => x.Id);
        m.Map(x => x.EnumProperty);     // this works
        m.Map(x => x.S);
    });

the script is generated correctly:

if exists (select * from dbo.sysobjects where id = object_id(N'[X]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [X]

create table [X] (
    Id INT not null,
   EnumProperty NVARCHAR(255) null,
   S NVARCHAR(255) null,
   primary key (Id)
)

This shows that there seems to be nothing wrong with NHibernate's ability to map the presented enum correctly. Why can't auto-mapping cope with this?


When I add the following method to MyAutoMappingConfiguration:

public override bool ShouldMap(Member member)
{
    var result = base.ShouldMap(member);
    return result;
}

and place the breakpoint, the result is true for the EnumProperty member, which somehow gets ignored later.

like image 535
BartoszKP Avatar asked Oct 31 '22 11:10

BartoszKP


1 Answers

In my experience enums are mapped out of the box, nothing extra to do at all (no custom types or components).

So, there are two problems:

  • IsComponent shouldn't indicate that the enum in question is a component:

    public override bool IsComponent(Type type)
    {
        return base.IsComponent(type);
    }
    

    (or just remove the implementation at all)

  • ShouldMap shouldn't indicate that the enum needs to be mapped explicitly. It will be mapped anyway, because it's a property. So, for example:

    public override bool ShouldMap(Member member)
    {
        return base.ShouldMap(member) && member.CanWrite &&
               !member.MemberInfo.IsDefined(typeof(NotMappedAttribute), false);
    }
    

    In your case, if the enum is in the same namespace you should do:

    public override bool ShouldMap(Type type)
    {
        return type.Namespace == "Domain"
            && !type.IsEnum;
    }
    

    (which is a bit counter-intuitive)

like image 98
jenson-button-event Avatar answered Nov 15 '22 05:11

jenson-button-event