свободное отображение отношений nhibernate — многие ко многим в одном объекте

#c# #nhibernate #fluent-nhibernate #many-to-many #entity-relationship

#c# #nhibernate #свободный-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();
  

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

Категория отношений.Дочерние категории для категории.ChildrenCategories имеет обратное значение с обеих сторон. Удалите инверсию с одной стороны отношения.

Что я нахожу странным, так это то, почему в нем упоминается «Категория.Дочерние категории ‘ для категории.Дочерние категории, в отличие от родительских категорий?

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

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

Комментарии:

1. У нас точно такая же проблема. Ответ был бы весьма признателен.

2. Если это действительно ошибка в FNH, вы всегда можете использовать традиционное сопоставление xml или обходные пути, представленные в ответах.

3. Я поднял проблему по этому поводу. Мы исправим это как можно скорее.

4. «Ошибка», похоже, все еще существует

Ответ №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>
  

Редактировать:
Покопавшись в исходном коде 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);
})
  

Комментарии:

1. Вы можете увидеть код проверки здесь github.com/jagregory/fluent-nhibernate/blob/release-1.2/src / … и, похоже, это все еще находится в последней версии FNH. Есть ли способ отключить проверку только для одной карты?

2. Да, это тег 1.2. Последний код находится в главной ветке ( github.com/jagregory/fluent-nhibernate/blob/master/src / … ) но я не тестировал версию из главной ветки, поэтому я не уверен, что она уже там (просто догадываюсь). Я не знаю, как отключить проверку для одного MapClass, но есть только две проверки. Ненужный и проверьте, сопоставлен ли идентификатор. Я буду счастливо жить без них обоих :).

3. Возможно, я неправильно понимаю, что происходит, но, похоже, основная ветвь устарела, в ней отсутствуют коммиты, которые находятся в 2.1. Я не вижу исправления этой проблемы ни в одной ветке.

4. Master устарел и всегда должен рассматриваться как экспериментальный. v1.x Ветвь — это то, что содержит текущий выпуск (и исправления, которые войдут в следующий выпуск). В какой-то момент две ветви сойдутся, но этого еще не произошло. Что касается этой проблемы, я создал для нее тикет , и мы займемся этим как можно скорее.

Ответ №2:

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

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

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

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

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

Комментарии:

1. Да, но я полагаю, что любые другие ошибки также будут подавлены, что может оказаться проблематичным для любых будущих изменений в сопоставлениях классов, которые никто не заметит?

2. Отлично замечено! Я (очевидно) не рассматривал этот сценарий. Я создал проблему для этого, и мы разберемся с ней как можно скорее.

3. Карл, да, отключение проверки отключит две проверки, которые я изложил в своем ответе. Это может вызвать проблемы, поскольку добавляется больше проверок. Однако ответ Якуба заключается в отключении того же набора проверок, просто с немного другим кодом.

4. Попробуйте AutoMappings.ValidationEnabled = false .

Ответ №3:

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

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

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

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

Комментарии:

1. Ситуация, с которой мы сталкиваемся, — это банковские счета, где некоторые счета закрыты, а деньги переведены на другие счета. Это создает связь «многие ко многим» от учетной записи к учетной записи.

2. Вам нужно было бы создать другой класс для привязки банковских счетов, чтобы обойти ошибку. У вас мог бы быть класс AccountLink , в котором были бы MainAccountID и LinkedAccountID . Ссылка на учетную запись будет иметь коллекцию «один ко многим» ‘LinkedAccounts’, которая имеет таблицу отношений «Один ко многим» AccountLink . Вы можете просмотреть отношения, выполнив MainAccount.LinkedAccounts[0].LinkedAccount. Надеюсь, это поможет!