2009-07-21 53 views
4

有人可以向我解釋這個小神祕的事情,關於NHibernate如何處理複合元素。爲什麼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發出一個選擇與加入獲得博客與帖子但然後刪除所有評論,然後插入註釋!它爲什麼這樣做?如果我不使用事務,那麼它將只執行select而不是DELETE和INSERT,就像我期望的那樣。我錯過了什麼?我正在使用NHibernate 2.0

回答

5

我認爲你需要覆蓋評論上的Equals()和GetHashCode()。 NHibernate沒有用於實體平等的ID,所以你必須定義什麼使得評論實體等同於另一個評論。

可能是錯的:)


編輯

來源: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)

-1

我的問題將是爲什麼你提交,如果你只需要做一個選擇?我相信它刪除所有註釋的原因是,當您調用事務提交時,博客對象及其關聯註釋將被緩存在用於創建事務的會話中。當您調用提交時,會導致會話中的所有對象被保存,導致保存回數據庫。我不清楚爲什麼它會刪除註釋,但保存對象是正確的行爲。

我也stumbled upon this today

NHibernate的被刪除我的整個 收集和重建它,而不是 更新表的。

這通常發生在NHibernate 找不到哪些項目更改爲集合中的 。常見的原因有:

  • 一個新的集合實例
  • 通過NHibernate的一個手動構造對象,並對其調用Update更換完全是一個持久化集合。
  • 序列化/反序列化持久集合顯然也會導致此問題。
  • 使用inverse =「false」更新a - 在這種情況下,NHibernate無法構造SQL來更新單個集合項目。

因此,爲了避免這個問題:

  • 傳遞您從NHibernate的回來吧(不一定在同一個會話)相同的集合實例,
  • 嘗試使用一些其他的集合,而不是(或)或
  • 嘗試使用inverse =「true」屬性。
+0

我認爲提交只會更新已經改變了實體 - 因爲沒有一個爲什麼會嘗試更新什麼?我也讀這個頁面http://ayende.com/Blog/archive/2008/12/28/nh-prof-alerts-use-of-implicit-transactions-is-discouraged.aspx – Gareth 2009-07-21 11:58:49

+0

我同意你不應該使用隱式事務,我只是不清楚爲什麼你沒有做任何修改就會執行這個事務。無論如何,我喜歡這個問題,答案非常豐富! – lomaxx 2009-07-21 23:31:01