беглый nhibernate - сопоставление отношений «многие ко многим» на одном объекте - PullRequest
20 голосов
/ 19 апреля 2011

У меня возникла проблема при попытке отобразить отношение многие ко многим, где обе стороны отношения ссылаются на одну и ту же сущность.Я использую Fluent NHibernate и NH3.1.

По сути, сценарий таков - у меня есть категория, которая может иметь несколько родителей.Таким образом, категория имеет несколько других категорий в качестве родителей, а также несколько других категорий в качестве своих дочерних элементов.

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

Однако, когда я пытаюсь построить фабрику, я получаю следующую ошибку:

Отношение Category.ChildrenCategories к Category.ChildrenCategories имеет значение Inverse, указанное с обеих сторон.Удалите Inverse с одной стороны отношения.

Что я нахожу странным, так это то, почему он упоминает Category.ChildrenCategories в Category.ChildrenCategories, а не ParentCategories?

Любая помощь будет принята с благодарностью!

Я только что создал награду за это, потому что это достаточно важно для меня.Пожалуйста, я не заинтересован в ответе "Вы не можете сделать это".

Ответы [ 3 ]

12 голосов
/ 12 мая 2011

Скорее всего, это ошибка FNH, и она, скорее всего, уже исправлена ​​в последнем исходном коде FNH .При использовании FNH1.0 и NH2.1 проблем нет.Эквивалентное отображение HBM хорошо работает в FNH1.2 и 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>

РЕДАКТИРОВАТЬ: После поиска в исходном коде FNH я нашел решение.Допустим, ваша конфигурация выглядит следующим образом:

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

Неудачный код может быть подавлен этой конфигурацией:

.Mappings(m => {
    var persistenceModel = new PersistenceModel();
    persistenceModel.AddMappingsFromAssembly(typeof(Category).Assembly);
    persistenceModel.ValidationEnabled = false; // this makes the trick
    m.UsePersistenceModel(persistenceModel);
})
7 голосов
/ 12 мая 2011

Эта проблема связана с проверкой / сопряжением отношений в Fluent NHibernate 2.1. FNH объединяет отношения , а затем проверяет, что только одна сторона отношения имеет .Inverse() указанное . Поскольку обе ссылки (родительский / дочерний) относятся к одному и тому же классу, они оба являются кандидатами в пары при сопоставлении. В этом случае FNH совпадает по названию сходства . Следовательно, каждый из них в паре с собой, а не друг с другом. Таким образом, размещение .Inverse() на любом из них запускает проверку (обе стороны пары имеют одно и то же отношение, которое является обратным).

Это можно исправить с помощью метода OverrideBiDirectionalManyToManyPairing() в FluentMappingsContainer. Теоретически, это позволит вам явно связать дочерние и родительские отношения. Однако в FNH 2.1 есть ошибка, и обратный вызов переопределения никогда не вызывается. ( Значение обратного вызова фиксируется до того, как его можно установить методом ).

В качестве обходного пути вы можете отключить все проверки в FNH. только две проверки . Во-первых, обе стороны отношений не имеют .Inverse(). Во-вторых, Id отображается на каждой сущности. Я нашел самый простой способ отключить проверку:

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

Этот подход позволяет отключить проверку, но при этом использовать полную выразительность конфигурации FluentMappings.

0 голосов
/ 16 мая 2011

Да, мне показалось, что это, скорее всего, ошибка в FNH, так как я попробовал это напрямую с NHibernate без использования Fluent NH, и это сработало. Однако, поскольку я уже настроил систему с использованием FNH, я не мог просто вернуться к тому, чтобы не использовать ее.

То, что я сделал, я сам создал как «класс в середине» для отношения «многие ко многим», которое обычно генерируется автоматически. Я создал страницу ContentPage_ChildLink, которая связывала категории Parents и Children. Это позволило мне работать с FNH и обойти проблему:)

В основном это ContentPage_ChildLink будет иметь два поля, ChildID и ParentID. Затем я мог бы установить «обратные» отношения отдельно, без каких-либо проблем.

Проблема с FNH, по-видимому, заключается в том, что у вас есть отношение многие ко многим, обе стороны которых относятся к одному и тому же классу. Единственный случай, о котором я могу думать, - это иерархическая структура, которая допускает наличие нескольких родителей.

...