Fluent-nhibernate: различать объекты для правильной загрузки иерархии - PullRequest
0 голосов
/ 10 июня 2009

Обновление

Ну, как мне сказали Стюарт Чарльз и Джеймс Грегори, моя модель была достаточно странной для начала. Очевидно, что двусторонние ссылки между классами при различении различных видов отношений не сделаны, и, по-видимому, по очень веской причине.

Я разрушил модель, изменил ее на другую, используя HasManyToMany между пользователями и Fiches, а затем добавил несколько кодированных проверок, чтобы убедиться, что мои пользователи не могут быть связаны более чем с одним Fiche.

Так что я думаю, что ответом на этот вид проблемы является своего рода предупреждение: «Не делай этого»;)

Спасибо вам обоим, что нашли время ответить!


Привет всем

Путь к правильному использованию Fluent Nhibernate труден, и, поскольку я начинаю чувствовать себя действительно ошеломленным, я подумал, что не помешает обратиться за помощью. Вот в чем дело.

Виновные

У меня есть следующие два класса, Fiche и User. Фиш должен иметь владельца пользователя и может иметь много последователей. С другой стороны, Пользователь может при необходимости быть привязан к одному и только одному Фишу. (Базовый класс EntityUpdateTrace содержит идентификатор guid и время создания / изменения для использования в PreSave / PreUpdate)

Public Class Fiche
    Inherits EntityUpdateTrace(Of Fiche)

    Private m_Owner As User
    Public Property Owner() As User
        ' snip

    Private m_Followers As IList(Of User)
    Public Property Followers() As IList(Of User)
        ' snip

End Class

Public Class User
    Inherits EntityUpdateTrace(Of User)

    Private m_Fiche As Fiche
    Public Property Fiche() As Fiche
        ' snip

End Class

У меня тогда есть следующее отображение

Public Class FicheMapping
Inherits ClassMap(Of Fiche)
Public Sub New()
    [Not].LazyLoad()
    Id(Function(f As Fiche) f.Id).GeneratedBy.GuidComb()
    References(Of User)(Function(f As Fiche) f.Owner).Not.Nullable()
    HasMany(Of User)(Function(f As Fiche) f.Followers).Inverse()
End Sub
End Class

Public Class UserMapping
    Inherits ClassMap(Of User)
    Public Sub New()
        [Not].LazyLoad()
        Id(Function(a As User) a.Id).GeneratedBy.GuidComb()
        References(Of Fiche)(Function(a As User) a.Fiche).Nullable()
    End Sub
End Class

Вопрос

Какого черта я делаю не так? :) Я не могу заставить эту модель работать, хотя она выглядит обманчиво простой.

  • Fiche загружает всех пользователей, связанных с ним; Звучит логично, и я думаю, мне следует различать определенный параметр, но, поскольку это будет что-то, полностью связанное с базой данных, мне не очень нравится идея (я пытаюсь поддерживать чистоту в чистоте классов в качестве упражнения в области гигиены домена). Так что, если Fiche veryImportantFiche создается Алисой, а затем Бобом, при перезагрузке подписчиков я нахожу Алису и Боба. Есть ли способ различать два типа пользователей?

  • Я хотел бы использовать список в базе данных, чтобы следить за порядком подписчиков, но как только я изменю отображение на

    HasMany (пользователя) (функция (f как фишка) f.Followers) .AsList (). Inverse ()

появляется следующая ошибка:

столбец нулевого индекса для коллекции: Последователи

Количество информации об этой ошибке на самом деле не является подавляющим, что наводит меня на мысль, что я неправильно отношусь к этой модели, что возвращает меня к первому вопросу ... Что, черт возьми, я делаю неправильно?

Спасибо всем за чтение и за понимание этого!

Ответы [ 2 ]

1 голос
/ 11 июня 2009

Похоже, вам нужно много ко многим вместо одного ко многим. Таким образом, на одного пользователя могут ссылаться несколько фишек.

Что касается порядка вашей коллекции, AsList не будет работать, если у вас в таблице нет столбца индекса; это столбец, который содержит числовое значение для каждой записи без пробелов. Если вам не нужно это поведение, вам нужно использовать атрибут order-by.

1 голос
/ 10 июня 2009

Ошибка List происходит из-за семантики списков. Это сложно, потому что пакеты также по умолчанию сопоставляются с IList, но это связано с отсутствием типа коллекции с семантикой «bag» в .NET Framework. В «сумке» концептуально нет порядка, потому что предметы просто бросаются в сумку и удаляются в любом порядке и могут легко перемещаться внутри сумки. Список, однако, по своей природе упорядочен и проиндексирован (представьте его как массив с дополнительной семантикой, поэтому каждый элемент имеет уникальное значение индекса). Полученное сообщение об ошибке указывает на то, что NHibernate хочет столбец, в котором хранится значение индекса для каждого элемента (поэтому оно должно быть уникальным и, поскольку это целое значение ant IList). Поскольку у вас нет столбца индекса, вам придется упорядочить их по-другому, возможно, добавив в запрос предложение ORDER BY.

Что касается первой проблемы, вам может потребоваться переосмыслить, как вы работаете с этим. На самом деле, вы можете использовать фильтры NHibernate , но у меня нет опыта, чтобы сказать, как это может сработать. Ваша коллекция Followers - это действительно все пользователи, которые имеют отношение к Fiche (все User s ссылаются на Fiche), так что это больше похоже на RelatedUsers. Используя шаблон репозитория, вы можете иметь метод, подобный FindFollowers(Fiche fiche), который будет запрашивать все RelatedUsers, где User не равен Owner. Этот шаблон может принести вам дополнительную пользу, поскольку вы хотите заказать User. Что-то вроде (C #, критерий запроса):

session.CreateCriteria(typeof(Fiche))
    .CreateCriteria("RelatedUsers", JoinType.InnerJoin)
        .Add(Restrictions.Not(Restrictions.Eq("Id", fiche.Owner.Id)))
        .AddOrder(Order.Asc("PropertyNameToOrderBy"))
        .List<User>();
...