2010-08-20 7 views
21

Próbuję odwzorować właściwość enum (instancja System.DayOfWeek) w moim modelu na pole z liczbą całkowitą. Inne właściwości wyliczeniowe w modelu powinny być odwzorowane na łańcuchy, więc nie chcę definiować konwencji.Wylicz na liczbę całkowitą, powodując aktualizacje dla każdego koloru.

Rozumiem, że powinno to być możliwe przy użyciu biegle mapowanie jak:

Map(x => x.DayOfWeek).CustomType<int>(); 

i rzeczywiście, na pierwszy rzut oka wydaje się działać.

Zauważyłem jednak, że wystąpienia obiektów z mapowanymi w ten sposób właściwościami są aktualizowane za każdym razem, gdy sesja była opróżniana, nawet jeśli nie wprowadzono do nich żadnych poprawek.

Aby dowiedzieć się, co jest przyczyną tego koloru, ustawiłem IPreUpdateEventListener i sprawdziłem stan OldState i State of the entity. Zobacz załączony obraz. W OldState odpowiednim obiektem jest int, podczas gdy w State jest DayOfWeek.

Jeśli korzystam z mapowania XML HBM bez określonego atrybutu typu, ten problem nie występuje.

Więc ...

Jest to błąd lub niedociągnięcie w GenericEnumMapper? Czy jest jakiś sposób na odwzorowanie FNH, aby nie podawał żadnego atrybutu typu na wygenerowanym HBM? Jeśli nie, czy mogę określić domyślny typ, który NH używa do wyliczenia (i co to jest)?

alt text

+0

Co się stanie, jeśli po prostu map bez CustomType? NH powinien sam się domyślić? –

+0

@ShaneC - NH będzie, ale zachowanie FNH domyślnie będzie próbowało utrzymywać wyliczenie jako ciąg. –

Odpowiedz

23

Jeśli używasz mojej konwencji wyliczeniowej, nie masz tego problemu.

public class EnumConvention : IPropertyConvention, IPropertyConventionAcceptance 
{ 
    public void Apply(IPropertyInstance instance) 
    { 
     instance.CustomType(instance.Property.PropertyType); 
    } 

    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) 
    { 
     criteria.Expect(x => x.Property.PropertyType == typeof(AddressType) || 
      x.Property.PropertyType == typeof(Status) || 
      x.Property.PropertyType == typeof(DayOfWeek)); 
    } 
} 

Można wtedy map aĹ jak regularna:

Map(x => x.DayOfWeek); 

EDIT: Updated konwencję odebrać konkretne teksty stałe użyć do konwersji int. Wszystkie wyliczenia, które nie zostały tutaj zaznaczone, zostaną zmapowane jako łańcuch. Być może będziesz musiał trochę poeksperymentować z tym, co właściwie przetestować. Nie jestem pewien, czy właściwość type zrobi to bezpośrednio.

+0

Czy mogę zastąpić tę konwencję przez większość wyliczeń, które chcę zmapować jako ciąg? –

+0

Z pewnością możesz. Wszystko jest w części akceptacji: http://stackoverflow.com/questions/439003/how-do-you-map-an-enum-as-an-int-value-with-fluent-nhibernate/2716236#2716236, aby uzyskać więcej info – mhenrixon

+0

Doskonale, właśnie wypróbowałem to i zachowuje się dokładnie tak, jak tego wymagam. Dzięki za pomoc @CatZ! –

4

Jeden obejście, które używam to mieć pole oporowe int i pozwalając NHibernate użyć dla mapowania.

Ilekroć NHibernate musi wykonać rzut, aby porównać nową wartość ze starą - jest zawsze oznaczony jako brudny - powodując flush.

+0

+1: Po prostu posiadasz publiczną właściwość, która reprezentuje wartość wyliczeniową, a następnie rzutujesz na/z int na swoim zapleczu - tak to zrobię ... – DanP

+0

Nie podoba mi się ten pomysł. Wtedy masz wiedzę na temat mechanizmu utrzymywania w obiekcie. I myślałem, że metoda CustomType <> była dla mapowania, w którym podajesz dziedziczenie typu z IUserType? Mogę się mylić. Spróbowałabym usunąć mapowanie CustomType i pozwolić, aby GenericEnumMapper bazujący na konwencjach wykonał to zadanie. Jedyne, co mi się nie podoba w GenericEnumMapper, to to, że jest podatny na zmianę kolejności wpisów w enum (zakładając, że nie ustawiasz wartości, których ja nie). – Rich

+0

Dzięki chłopaki, skłonni to zaakceptować, wydaje się, że jest to bezpieczne i proste rozwiązanie. –

0

To zależy od tego, czy musisz mieć DayOfWeek jako liczbę całkowitą.

Jeśli przesyłasz jako część mapowania, równość zawsze kończy się niepowodzeniem, a właściwość zostanie oznaczona jako zabrudzona.

I pewnie map:

mapie (x => x.DayOfWeek) .CustomType();

i utwórz właściwość tylko do odczytu, która przedstawia wartość DayOfWeek jako liczbę całkowitą, jeśli jest naprawdę wymagana. Bez względu na to, mapowanie jako rzeczywisty typ powinno działać i zapobiegać fałszywym-brudnym.

0

Możesz rozważyć alternatywne podejście; Zauważyłem, że użycie Fabio Maulo w wersji well known instance types jest nieocenione w takich zastosowaniach. Korzyści z nich są natychmiast widoczne za każdym razem, gdy próbujesz rozszerzyć to, co podstawowe wyliczenie może zrobić (np. Podanie zlokalizowanego opisu itp.).

1

Prostym sposobem, który zadziałał, była zmiana niestandardowego typu odwzorowania z int na PersistentEnumType. Upewnij się, aby zadeklarować wersji rodzajowy, aby ułatwić Ci życie:

public class PersistentEnumType<T> : PersistentEnumType { 
    public PersistentEnumType() : base(typeof(T)) {} 
} 

Następnie użyj

Map(x => x.DayOfWeek) 
    .CustomType<PersistentEnumType<System.DayOfWeek>>(); 

nie wymaga zmian w jednostkach, tylko odwzorowań i może być stosowany na swoim majątku na podstawa.

Zobacz więcej here.

+0

Ładne rozwiązanie, które działa również z rozszerzeniem Orchard 'ISessionConfigurationEvents'. Po prostu dodaj klasę, która implementuje 'ISessionConfigurationEvents.Created()' i wstaw 'defaultModel.Override (mapowanie => mapowanie.Mapa (x => x.DayOfWeek) .CustomType ())' tam i pamiętaj o usunięciu 'mappings.bin' przed ponownym uruchomieniem Orchard. – ViRuSTriNiTy

Powiązane problemy