płynne mapowanie relacji NHibernate-many-to-many na tej samej jednostce

Mam problem starając się odwzorować wiele do wielu relacji, gdzie obie strony relacji odnoszą się do tej samej istoty. Używam Fluent NHibernate i NH3.1.

Zasadniczo scenariusz jest taki - mam kategorię, która może mieć wielu rodziców. Tak więc kategoria ma wiele innych kategorii jako rodzice, a także wiele innych kategorii jako Dzieci.

HasManyToMany(x => x.ParentCategories).AsBag().Table("parentcategorychildren").ParentKeyColumn("ChildID").ChildKeyColumn("ParentID").Cascade.SaveUpdate();
HasManyToMany(x => x.ChildrenCategories).AsBag().Table("parentcategorychildren").ParentKeyColumn("ParentID").ChildKeyColumn("ChildID").Inverse();

Jednak, kiedy próbuję zbudować fabrykę, dostaję następujący błąd:

Kategoria relacji.Dziecikategorie do kategorii.ChildrenCategories ma odwrotność określoną po obu stronach. Usuń odwrotność z jednej strony Związku.

To, co uważam za dziwne, to dlaczego wymienia " kategorię.Dziecikategorie " do kategorii.Kategorie dzieci, w przeciwieństwie do kategorii rodziców?

Każda pomoc będzie bardzo mile widziana !

Stworzyłem nagrodę za to, bo to jest dla mnie wystarczająco ważne. Proszę, nie jestem zainteresowany. w "nie możesz tego zrobić" jako odpowiedź.

Author: Michael Meadows, 2011-04-19

3 answers

Jest to najprawdopodobniej błąd FNH i najprawdopodobniej został już naprawiony w najnowszym kodzie źródłowym FNH . Nie ma problemu przy użyciu FNH1. 0 i NH2. 1. Analogiczne odwzorowanie HBM działa dobrze w FNH1. 2 i NH3. 1:

<bag name="ParentCategories" cascade="all" table="parentcategorychildren">
    <key column="ChildID" />
    <many-to-many column="ParentID" class="Category" />
</bag>

<bag name="ChildrenCategories" inverse="true" table="parentcategorychildren">
    <key column="ParentID" />
    <many-to-many column="ChildID" class="Category" />
</bag>

Edytuj: Po kopaniu w kodzie źródłowym FNH znalazłem obejście. Załóżmy, że Twoja konfiguracja wygląda tak:

.Mappings(m => {
    m.FluentMappings.AddFromAssemblyOf<Category>();
})

Pechowy kod może być tłumiony przez tę konfigurację:

.Mappings(m => {
    var persistenceModel = new PersistenceModel();
    persistenceModel.AddMappingsFromAssembly(typeof(Category).Assembly);
    persistenceModel.ValidationEnabled = false; // this makes the trick
    m.UsePersistenceModel(persistenceModel);
})
 12
Author: Jakub Linhart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-12 05:09:20

Jest to problem z walidacją/parowaniem relacji Fluent NHibernate 2.1. FNH paruje relacje , a następnie potwierdza, że tylko jedna strona relacji ma .Inverse() określone. Ponieważ oba odniesienia (rodzic/dziecko) są do tej samej klasy, oba pasują do kandydatów podczas parowania. W takim przypadku FNH pasuje do podobieństwa nazw. W konsekwencji, każdy z nich jest sparowany ze sobą, a nie ze sobą. Więc umieszczając .Inverse() na którymś z uruchamia walidację (obie strony pary są tą samą relacją, która jest odwrotna).

Powinno być możliwe skorygowanie tego za pomocą metody OverrideBiDirectionalManyToManyPairing() w programie FluentMappingsContainer. Teoretycznie, to pozwoli Ci wyraźnie powiązać relacje między dzieckiem i rodzicem. Jednak w FNH 2.1 jest błąd, i override callback nigdy nie jest wywoływany. (wartość wywołania zwrotnego jest przechwytywana, zanim może być ustawiona metodą ).

Jako obejście, można wyłączyć wszystkie Walidacja w FNH. Istnieją tylko dwie walidacje . Po pierwsze, że obie strony Związku nie mają .Inverse(). Po drugie, że identyfikator jest mapowany na każdym obiekcie. Najczystszym sposobem, jaki znalazłem, aby wyłączyć walidację, jest:

.Mappings(m => {
    var persistenceModel = new PersistenceModel() { ValidationEnabled = false };
    m.UsePersistenceModel(persistenceModel)
     .FluentMappings.AddFromAssemblyOf<Category>();
})

To podejście pozwala wyłączyć walidację, ale nadal używać pełnej ekspresji konfiguracji FluentMappings.

 6
Author: Jeff Walker Code Ranger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-12 20:21:58

Tak wydawało mi się, że najprawdopodobniej był to błąd w FNH, ponieważ próbowałem go bezpośrednio z NHibernate bez używania Fluent NH i zadziałało. Jednak ponieważ już skonfigurowałem system za pomocą FNH, nie mogłem po prostu powrócić do tego, że go nie używałem.

To, co zrobiłem, to stworzyłem siebie jako "klasę w środku" dla relacji wielu do wielu, która normalnie jest generowana automatycznie. Stworzyłem stronę ContentPage_ChildLink, która łączyła kategorie Parents i Children. To pozwoliło mi pracować z FNH i obejść problem:)

Zasadniczo to ContentPage_ChildLink będzie miało dwa pola, ChildID i ParentID. Mógłbym wtedy ustawić "odwrotne" relacje osobno, bez żadnego problemu.

Problem z FNH wydaje się być wtedy, gdy masz wiele do wielu relacji, które obie strony są tej samej klasy, jedyny przypadek mogę myśleć jest struktura hierarchii, która pozwala na wielu rodziców.

 0
Author: Karl Cassar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-16 09:32:32