2011-03-05 37 views
1

什麼HBM我必須寫BlogPost有這些表之間的雙向關係?

我試圖從兩邊many-to-one但碰到以下問題(很可能是因爲我做到了完全錯誤的):NHibernate的許多-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> 

所需DB結構:

+------------------------------+ 
| 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) | 
+--------------+---------------+ 
+0

也許我不清楚爲什麼這是所需的結構;如果一篇文章屬於博客,那麼爲什麼評論屬於帖子沒有足夠的信息來確定它在哪個博客? – Paul 2011-03-05 19:30:45

+1

@保羅,我提到的例子是人爲的。我真正的例子是在這裏嘗試一個解釋很複雜。 – 2011-03-05 19:52:10

回答

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

請注意,您需要致電保存評論;別的什麼都會失敗。

+0

你好迭戈,謝謝你用來回答這個問題的麻煩。它現在正在完美工作。有趣的是,設置'dynamic-update = true'就足以讓我的真實生活場景適用。我在「Blog」表上有一些事件監聽器,它將審計字段更改應用於它。沒有這個設置就會失敗。這是讓它工作的關鍵,我不知道你如何知道它的增加,只是輝煌的,謝謝! – 2011-03-06 05:01:28