2010-09-15 35 views
1

我有兩個實體,一個ShelfProduct爲什麼Session.Flush()需要保持關係?

public class Shelf 
{ 
    public virtual IList<Product> Products { get; set; } 

    public Shelf() 
    { 
     Products = new List<Product>(); 
    } 
} 

public class Product 
{ 
    public virtual string Name { get; set; } 
} 

基本上說,一個Shelf可以包含很多Products,並且Product可以在很多Shelves放。因此,ShelfProduct之間存在單向多對多關係。當我運行下面的代碼:

var shelf = new Shelf(); 
var product = new Product { Name = "Peas" }; 
shelf.Products.Add(product); 

using (var session = SessionFactory.OpenSession()) 
{ 
    session.Save(shelf); 
} 

的NHibernate將保存ProductShelf,但它不會救他們之間的關係,因此,如果您檢索Shelf,它將包含零Products

但是,如果我添加一個session.Flush()調用,它將正確保存關係,以便檢索Shelf將返回一個Product

本博客文章的詳細信息我的問題:

http://www.neeraj.name/2005/07/02/hibernate-session-close-does-not-call-session-flush.html

不過,我想知道爲什麼需要這個session.Flush()通話。看起來與直覺相反,保存Shelf以正確的級聯行爲將保存Product,但除非我刷新會話,否則無法建立兩者之間的關係。在我看來,Save()調用應該節省所有內容,而不僅僅是實體本身沒有他們的關係。

回答

1

Save不僅標誌着被持久化的實體,並生成一個標識符。它不會保留對數據庫的更改。

flushing發生在不同時刻,所有更改(插入,更新和刪除)。

但是,交易也應該始終使用。正確的工作流是(大約):

using (var session = factory.OpenSession()) 
using (var tx = session.BeginTransaction()) 
{ 
    //create and manipulate objects 
    session.Save(newObjectToBePersisted); 
    tx.Commit(); 
} 
+0

感謝迭戈,這完美地回答了我的問題! – 2010-09-15 19:16:27

0

我不知道肯定,但也許是因爲主鍵的。當您保存兩個trancident對象並使用Identity作爲主鍵生成模型時,Nhibernate不知道多對多連接表的Id。

在現實詞的用法你應該總是包裝所有操作在交易的實體。當您提交事務時,所有更改都將刷新到數據庫。在你提交之前,你爲什麼要嘗試選擇已經選擇的實體?

0

是否使用手動沖洗模式?如果您將其設置爲自動,則會在需要時立即執行。如果您在交易中運行,則需要執行session.getTransaction().commit()以確保更改不變。 Hibernate會在運行一個可能有錯誤結果的查詢之前或在提交事務之前刷新會話。

你可以配置Hibernate救子對象的集合,當父被保存。閱讀關於持久性傳遞的部分

(以下鏈接,在註釋文檔頁)(聲明:我用java休眠,不NHibernate的)

+0

文檔說明休眠模式沖洗是在這裏:http://docs.jboss.org/hibernate/stable/core/reference/en/html/objectstate.html#objectstate-沖洗 – RMorrisey 2010-09-15 08:09:05