2013-07-30 35 views
0

我有一個NHibernate映射,它定義了一個類型的HasMany關係,即一個類有另一個類的列表。從HasMany讀取未經處理的數據 - 與NHibernate的關係

我希望NHibernate能夠讀取未提交的數據,包括由HasMany關係產生的列表。

我有isolationlevel ReadUncomitted,我可以在提交之前寫入數據並讀回數據。

但是,列表總是空的,除非我首先提交。

有沒有辦法讓NHibernate使用來自HasMany關係的數據填充對象?

EDIT

原來在一個類中的任何非原始類型由未提交的讀填充,除非它們被實際添加到類。

例如,類Foo有一個列表Member它在數據庫中由Id連接。如果我堅持的Foo實例和Member使用NHibernate的數據庫實例無一不是實際上由Id值相關,那麼FooMember預期的情況下,如果我之前讀回未提交的(即完成交易)。

public class Member 
{ 
    Guid Id{ get; set; } 
} 

public class Foo 
{ 
    List<Member> MemberList{ get; set; } 
} 

// the mapping 
public class FooMap 
{ 
    HasMany(x => x.MemberList).KeyColumn("Id").PropertyRef("Id"); 
} 

但是,如果我創建的Foo實例和Member一個實例,並設置後者爲前者的參考和使用NHibermate堅持兩到數據庫,然後Foo有預期的情況下Member當我在完成交易前閱讀它。

如果我完成了交易,那麼Foo將在隨後的讀取中具有預期的Member實例;只要交易完成,Member是否僅存在具有正確FK的數據庫記錄至Foo或它是否參考Foo是無關緊要的。

經修訂的課題: 很可能已經NHibernate的基礎上FK-關係填充複雜的成員只有期間未提交讀?

回答

0

似乎這裏是一些一般的混亂,所以要澄清一些事情:

  • 事務隔離級別僅影響變更從其他 交易是可見的。事務總是可以讀回它自己修改過的數據。

  • 如果遵循的調用commit()的交易無關,與是否 或不擁有該事務可以讀取這些變化 或不NHibernate會話。它總是可以的。

  • 但是,NHibernate不會修改已經加載的實例。您作爲模型的開發者 負責對已加載的實體進行更改,確保模型 仍然有效並與您的業務規則一致,然後NHibernate將 將更改存儲在數據庫中。這是不是 NHibernate的工作,使您的一部分模型 與您在另一部分中所做的更改一致。

  • 在Commit()調用之前或之後的回讀無關緊要,因爲NHibernate 保證一個會話最多隻包含每個實體的一個副本。因此,當您查詢剛剛保存的對象時,您將返回相同的,已加載的未修改實例 。

  • 重要的是如果您關閉會話併爲您的查詢打開一個新的會話。然後,NHibernate將再次實例化對象,它將反映數據庫的當前狀態 。如果在會話中使用了 Clear()或Evict()(在調用Flush()或Commit()之後),原始會話中可能會產生相同的效果。這些 方法從會話中刪除已加載的實例,因此當您下一次查詢它時,會話將創建一個新實例,當然這會反映當前數據庫的狀態,如當前事務中可見的那樣。

+0

這個問題是[與此鏈接](http:///stackoverflow.com/questions/18128666/nhibernate-populate-list-with-uncommitted-data-related-only-by-fk-in-database)@oskar也回答了。他建議使用Flush(),Evict()或Clear()讓NHibernate更新已經加載的對象。 – hlintrup

+1

@ h.alex也提示Flush();但是,只有Evict(obj)或Clear()纔有效果。 – hlintrup

0

當你實例化一個新對象時,它自然包含所有屬性的默認值+通過構造函數設置的值。

這意味着您必須查詢您的實體對象才能獲取其中的任何持久數據。

因此,例如如果我們有這兩個類

public class Customer 
{ 
    public virtual Guid Id { get; set; } 
    public virtual ICollection<Order> Orders { get; set; } 
} 

public class Order 
{ 
    public virtual Guid Id { get; set; } 

    public virtual string Description { get; set; } 
    //todo add items 
} 

那麼我們就需要這樣的方法:

public Customer GetCustomerWithUncommitedOrders(Guid customerId) 
{ 
    ITransaction t = null; 
    Customer customer = null; 

    try 
    { 
     t = session.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted); 


     customer = session.QueryOver<Customer>().Where(x => x.Id == customerId).Fetch(x => x.Orders).Eager.List(); 


     t.Commit(); 
    } 
    catch (Exception ex) 
    { 
     //todo log 

     if (t != null) 
      t.Rollback(); 
    } 
    finally 
    { 
     if (t != null) 
      t.Dispose(); 
    } 

    return customer; 
} 

然後,我們可以編輯的客戶,並將其保存在另一個(或相同,這取決於「編輯」持續時間)交易。 但是,這可能會帶來併發擔憂。

+0

我想要的是''SaveOrUpdate'一個'客戶'對象與一些'訂單'在裏面,並讀取整個事情而不提交。現在的問題是'Id'將在沒有提交的'SaveOrUpdate'後被正確讀回,但是列表是空的。你對這種行爲有什麼建議嗎? – hlintrup

+0

你能發表一些代碼嗎?好吧,在saveorupdate()之後,您可以在會話對象上調用flush()。這應該/可以更新客戶。 –

+0

'Flush'沒有效果,只有'Commit'。 地圖看起來像這樣: '的hasMany(X => x.PspList).KeyColumn( 「PayExAgreementRef」)Not.LazyLoad()Cascade.DeleteOrphan()反向();' 如果使用'(。 nolock)'在管理工作室中,我可以看到所有的數據都在db中,但是NHibernate沒有解決它。 – hlintrup