2017-06-12 61 views
3

我想對我發現,當我使用INSERT命令與NHibernate的無狀態會話行爲的意見(NB。我使用NHibernate的2.1.2)NHibernate的無國籍插入行爲

的情況是這樣的

//STATEFULL SESSION 
var session = sessionFactory.OpenSession() 
using(var transaction = session.BeginTransaction()){ 
    var entity = new MyEntityType(); 
    entity.Id = 1; 

    session.Save(entity); 

    var entity2 = session.Get<MyEntityType>(1); 
    //OK! It returns saved entity...as I expect 

    transaction.Commit(); 
} 

但是......對無狀態會話,行爲改變...

//STATELESS SESSION 
var session = sessionFactory.OpenStatelessSession() 
using(var transaction = session.BeginTransaction()){ 
    var entity = new MyEntityType(); 
    entity.Id = 1; 

    session.Insert(entity); 

    var entity2 = session.Get<MyEntityType>(1); 
    //entity2 IS NULL!!! Why? 

    transaction.Commit(); 
} 

我的問題是...我怎麼能檢查如果我已經插在無狀態會話的事務範圍的項目?

+0

請原諒我,但是您的應用程序是否實現了NHibernate具有的工作單元模式? –

回答

2

那麼,無國籍是...無國籍。所以沒有會話緩存讓你插入的實體從內存返回。

現在,它爲什麼不讀取數據庫?因爲它還沒有在那裏!

很有可能你已啓用配料(adonet.batch_size XML配置參數,或通過代碼Environment.BatchSize配置屬性,或者沒有通過IStatelessSession.SetBatchSize(int)禁用它,而它是在會話工廠級別啓用)。啓用批處理後,如果您的NHibernate數據庫驅動程序支持它,則會盡可能將DML操作批處理到最大配置的批處理大小,然後刷新到數據庫。

所以可能會出現一個無狀態的會話這樣的沖洗:達到

  • 如果「批量」操作,以執行計數。
  • 如果交易被提交。
  • 如果另一個DML查詢不僅與其參數值有所不同,
    (對於您的情況,例如在插入後插入另一種實體,或在插入後更新或刪除任何類型的實體)。
  • 通過明確刷新批處理器,輕擊內部會話接口。
    s.GetSessionImplementation().Flush();

如果您希望您的Insert立即發送到數據庫,禁用配料。將其設置爲0將禁用它。

但爲什麼你首先使用無狀態會話?可能以高性能的方式插入大量實體。在這種情況下,禁用批處理將會值得您的目的。

所以你可以改爲通過會話GetSessionImplementation()方法暴露內部會話接口,並明確Flush它。但是,直接調用內部函數可能會產生未定義的行爲,所以這不是推薦的做法。

+0

無狀態會話不支持批處理IMO。調用'SetBatchSize()'方法會拋出異常。它是否正確? –

+0

不,它確實以有限的方式支持它,但確實如此。您可能會爲整個會話工廠禁用配料。在這種情況下,會話工廠會爲所有會話產生「NonBatchingBatcher」,並嘗試在其上設置批量大小失敗。事實上,'SetBatchSize'僅用於更改未禁用的批處理大小或禁用它。 –