5

Mam następujący typ wyliczeniowy:Dlaczego funkcja automatycznego mapowania z NHibernate Fluent ignoruje typ wyliczeniowy?

public enum EnumType 
{ 
    E1, 
    E2 
} 

stosowane w poniższej klasy:

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

    public virtual EnumType EnumProperty { get; set; } 

    public virtual string S { get; set; } 
} 

chcę utrzymywać wystąpień tego typu w bazie danych przy użyciu NHibernate. I aby uniknąć pisania kodu szablonowe, staram się korzystać z funkcji automatycznego mapowania następująco:

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(); 
} 

gdzie MyAutoMappingConfiguration wygląda następująco:

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"; 
    } 
} 

Gdy używam schematu wygenerowany z takiej konfiguracji, aby utworzyć baza:

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

Poniższy skrypt jest generowany i stracony:

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) 
) 

Dlaczego ignoruje się właściwość EnumProperty?

Kiedy dodać wyraźne odwzorowanie dla X, lub (co wydaje odpowiednik) przesłonięcie do automatycznego mapowania tak:

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); 
    }); 

skrypt jest generowany poprawnie:

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) 
) 

to pokazuje wydaje się, że nie ma nic złego w zdolności NHibernate do prawidłowego odwzorowania prezentowanego wyliczenia. Dlaczego automatyczne mapowanie nie może sobie z tym poradzić?


Kiedy dodać następującą metodę MyAutoMappingConfiguration:

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

i umieścić punkt przerwania The result jest true dla członka EnumProperty, która w jakiś sposób zostanie zignorowany później.

+0

Z pewnych przyczyn wydaje się domyślnie wyłączone podczas korzystania z automapie. https://groups.google.com/forum/#!topic/fluent-nhibernate/NJo0FiWXEwY – Najera

+0

@Najera Poniżej znajduje się mój komentarz] Odpowiedź DeJaVo] (http://stackoverflow.com/a/34714996/2642204). – BartoszKP

+0

Kiedy wykonywany jest mehod jest pusty, ale delegat jest wykonywany? Jeśli tak, Twoja nieruchomość jest oceniana? – Najera

Odpowiedz

2

Z mojego doświadczenia wynika, że ​​wyliczenia są mapowane po wyjęciu z pudełka, bez żadnych dodatkowych czynności (bez niestandardowych typów lub komponentów).

Tak, istnieją dwa problemy:

  • IsComponent nie powinien wskazywać, że enum w pytaniu jest składnikiem:

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

    (lub po prostu usunąć realizację w ogóle)

  • ShouldMap nie powinien sugerować, że wyliczenie musi być jawnie odwzorowane. Zostanie to zmapowane, ponieważ jest to własność.Tak więc, na przykład:

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

    w przypadku, jeśli enum jest w tej samej przestrzeni nazw należy zrobić:

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

    (co jest sprzeczne z intuicją bit)

+0

Nie jest jasne, co mam zrobić. Musisz mapować Enum, więc dlaczego miałbyś wstawić '! Type.IsEnum'? Mówisz o członku lub wpisujesz "ShouldMap"? Możesz dowolnie edytować odpowiedź. –

+2

Tak, "mapa" powinna być używana tylko w kontekście całych podmiotów, a nie ich właściwości - to był główny problem z moim podejściem. Zmieniłem twoją odpowiedź, aby to wyjaśnić - napraw to, jeśli uważasz, że nie jest wystarczająco jasne. Dzięki jeszcze raz! – BartoszKP