Подтвердить что ты не робот

Плавное nhibernate - сопоставление отношений много-ко-многим на одном объекте

У меня возникла проблема с поиском отношения "многие ко многим", где обе стороны отношения ссылаются на одну и ту же сущность. Я использую 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();

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

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

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

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

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

4b9b3361

Ответ 1

Скорее всего, это ошибка 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>

EDIT: После копания в исходном коде 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);
})

Ответ 2

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

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

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

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

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

Ответ 3

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

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

В основном это ContentPage_ChildLink имеет два поля: ChildID и ParentID. Я мог бы установить отношения "Обратный" отдельно, без каких-либо проблем.

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