Почему NHibernate удаляет, а затем вставляет составные элементы в select? - PullRequest
4 голосов
/ 21 июля 2009

Может кто-нибудь объяснить мне эту маленькую загадку о том, как NHibernate работает с составными элементами.

У меня есть классы, которые выглядят так:

public class Blog
{
    public virtual int Id
    {
        get;
        private set;
    }

    public virtual ISet<Comment> Comments
    {
        get;
        set;
    }
}

public class Comment
{
    public virtual string CommentText
    {
        get;
        set;
    }

    public virtual DateTime Date
    {
        get;
        set;
    }
}

и такие сопоставления;

<class name="Blog" table="blog">
    <id name="Id" column="id" unsaved-value="0">
      <generator class="hilo"/>
    </id>

    <set name="Comments" table="blog_comments">
      <key column="blog_id" />
      <composite-element class="Comment">
        <property name="CommentText" column="comment" not-null="true" />
        <property name="Date" column="date" not-null="true" />
      </composite-element>
    </set>

  </class>

Однако, когда я выполняю выбор, подобный этому;


using (ITransaction transaction = session.BeginTransaction())
{
    Blog blog = session.CreateCriteria(typeof(Blog))
                  .SetFetchMode("Comments", FetchMode.Eager)
                  .Add(Expression.IdEq(2345))            
                  .UniqueResult();

    transaction.Commit();
}

NHibernate выдает выбор с объединением, чтобы получить блог с сообщениями, НО затем удаляет все комментарии и затем вставляет комментарии! Почему он это делает? Если я не использую транзакцию, тогда она выполнит ТОЛЬКО выбор, а не УДАЛЕНИЕ и ВСТАВКА, как я ожидал. Что мне не хватает? Я использую NHibernate 2.0

Ответы [ 2 ]

6 голосов
/ 21 июля 2009

Я думаю, вам нужно переопределить Equals () и GetHashCode () для Comment. NHibernate не имеет идентификатора для обеспечения равенства сущностей, поэтому вы должны определить, что делает сущность комментария равной другому комментарию.

Может быть не так:)


Редактировать

От: http://www.nhforge.org/doc/nh/en/index.html#components-incollections (7,2)

Примечание: если вы определяете ISet составных элементов, очень важно правильно реализовать Equals () и GetHashCode ().

И пример реализации Equals / GetHashCode

http://www.nhforge.org/doc/nh/en/index.html#persistent-classes-equalshashcode (4,3)

0 голосов
/ 21 июля 2009

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

Я тоже наткнулся на это сегодня :

NHibernate удаляет всю мою сбор и воссоздание его вместо обновления таблицы.

Это обычно происходит, когда NHibernate не могу понять, какие элементы изменились в коллекции. Общие причины:

  • полная замена постоянной коллекции новым экземпляром коллекции
  • Передача NHibernate созданного вручную объекта и вызов на него Обновления.
  • Сериализация / десериализация постоянной коллекции, очевидно, также вызывает эту проблему.
  • обновление с помощью inverse = "false" - в этом случае NHibernate не может создать SQL для обновления отдельного элемента коллекции.

Таким образом, чтобы избежать проблемы:

  • передать обратно тот же экземпляр коллекции, который вы получили из NHibernate (не обязательно в том же сеансе),
  • попробуйте использовать другую коллекцию вместо (или) или
  • попробуйте использовать атрибут inverse = "true" для.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...