NHibernate多对一和双向访问

时间:2011-03-05 18:49:14

标签: .net nhibernate nhibernate-mapping many-to-one

我必须为BlogPost编写哪些HBM才能在这些表之间建立双向关系?

我试过双方many-to-one但遇到了以下问题(很可能是因为我做错了):

  • 在一个Session中插入对象图的瞬态持久性错误。
  • BlogPost表互相引用的外键问题。

注意:我的例子是人为的,请不要争论设计。

设计

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 个答案:

答案 0 :(得分:1)

如果博客属性需要不为空,则需要添加博客属性(请参阅6.4. One-To-Many Associations中的最后一段)

以下是一些应该有效的映射:

<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

请注意,您需要在评论上调用保存;其他任何事情都会失败。