Многоуровневый доступ NHibernate и двунаправленный доступ - PullRequest
2 голосов
/ 05 марта 2011

Какой HBM я должен написать для Blog и Post, чтобы иметь двунаправленную связь между этими таблицами?Я попытался many-to-one с обеих сторон, но столкнулся со следующими проблемами (скорее всего потому, что я сделал это совершенно неправильно):

  • Временные ошибки персистентности, вставив граф объекта в один Session.
  • Проблемы с внешним ключом в таблицах Blog и Post, ссылающихся друг на друга.

Примечание : Мой пример надуманный, не спорьте с дизайном.

Дизайн:

Design

Источник:

public class Blog
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Comment LastComment { get; set; }  // last-comment

    public virtual IList<Post> Posts { get; set; }
}

public class Post
{
    public virtual int Id { get; set; }
    public virtual string Content { get; set; }

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

public class Comment
{
    public virtual int Id { get; set; }
    public virtual string Feedback { get; set; }
    public virtual Blog Blog { get; set; } //commented-on
}

HBM:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Sample" 
 namespace="Sample">
  <class name="Blog">
    <id name="Id">
      <generator class="hilo" />
    </id>
    <property name="Name" />
    <!-- How to map Comment? -->
    <bag name="Posts">
      <key column="BlogId" />
      <one-to-many class="Post" />
    </bag>
  </class>

  <class name="Post">
    <id name="Id">
      <generator class="hilo" />
    </id>
    <property name="Feedback" />
    <bag name="Comments">
      <key column="PostId" />
      <one-to-many class="Comment" />
    </bag>
  </class>

  <class name="Comment">
    <id name="Id">
      <generator class="hilo" />
    </id>
    <property name="Comment" />
    <!-- How to map back to Blog? -->
  </class>
</hibernate-mapping>

Требуемая структура БД:

+------------------------------+
| Blog                         |
+--------------+---------------+
| Id           | int           |
| Name         | nvarchar(50)  |
| LastCommentId| int (null)    |
+--------------+---------------+

+------------------------------+
| Post                         |
+--------------+---------------+
| Id           | int           |
| BlogId       | int           |
+--------------+---------------+

+------------------------------+
| Comment                      |
+--------------+---------------+
| Id           | int           |
| PostId       | int           |
| BlogId       | int (not-null)|
| Feedback     | nvarchar(200) |
+--------------+---------------+

1 Ответ

1 голос
/ 06 марта 2011

Вам необходимо добавить свойство Blog к Post , если оно должно быть ненулевым (см. Последний абзац в 6.4. Ассоциации «один ко многим» )

Вот некоторые сопоставления, которые должны работать:

<class name="Blog" dynamic-update="true">
  <id name="Id">
    <generator class="..."/>
  </id>
  <property name="Name" />
  <many-to-one name="LastComment" column="LastCommentId" cascade="all" />
  <bag name="Posts" cascade="all" inverse="true">
    <key column="BlogId" />
    <one-to-many class="Post" />
  </bag>
</class>
<class name="Post">
  <id name="Id">
    <generator class="..."/>
  </id>
  <property name="Content" />
  <many-to-one name="Blog" column="BlogId" />
  <bag name="Comments" inverse="true">
    <key column="PostId" />
    <one-to-many class="Comment" />
  </bag>
</class>
<class name="Comment">
  <id name="Id">
    <generator class="..."/>
  </id>
  <property name="Feedback" />
  <many-to-one name="Blog" column="BlogId" not-null="true" cascade="all" />
</class>

Тогда вы сможете использовать код, подобный следующему:

using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    var blog = new Blog { Name = "My Blog" };
    var post = new Post { Blog = blog, Content = "My First Post" };
    var comment = new Comment { Blog = blog, Feedback = "Awesome!" };
    blog.LastComment = comment;
    blog.Posts = new List<Post> { post };
    post.Comments = new List<Comment> { comment };
    session.Save(comment);
    tx.Commit();
}

Это вставляет Блог , затем Пост , затем Комментарий , затем он обновляет Блог , чтобы установить LastCommentId .

Обратите внимание, что вам нужно позвонить Сохранить на Комментарий ;все остальное потерпит неудачу.

...