2016-04-15 51 views
1

我有一個問題,我的插入與NHibernate插入靜默失敗與NHibernate

交易始好, 我的選擇正確, 我從序列中選擇下一個值也 並提交事務, 但是,沒有插入出現在我的NHprofiler中,並且沒有錯誤出現。 我使用Session.OpenSession(ReadCommited)&交易 任何想法會發生什麼?

代碼

class NHUnitOfWok : INHibernateUnitOfWork 
{ 
    private readonly ISession _session; 
    private bool _isDisposed; 
    private IsolationLevel _isolationLevel; 

    public NHUnitOfWok(ISession session) 
    { 
     _session = session; 
     _session.FlushMode = FlushMode.Never; 
     _isolationLevel = IsolationLevel.ReadCommitted; 
    } 

    internal ISession Session 
    { 
     get { return _session; } 
    } 

    public void SaveChanges() 
    { 
     Session.Flush(); 
    } 

    public void CancelChanges() 
    { 
     Session.Clear(); 
    } 

    public void Commit() 
    { 
     Session.Transaction.Commit(); 
    } 

    public void Rollback() 
    { 
     Session.Transaction.Rollback(); 
    } 


    public void WithinNewSession(Action<ISession> actionToExecute, IsolationLevel? isolationLevel = null) 
    { 
     using (var tempSession = Session.SessionFactory.OpenSession()) 
     { 
      using (var transaction = tempSession.BeginTransaction(isolationLevel ?? _isolationLevel)) 
      { 
       actionToExecute(tempSession); 
       transaction.Commit(); 
      } 
     } 
    } 

    public void WithinTransaction(Action action, IsolationLevel? isolationLevel = null) 
    { 
     Enforce.NotNull(action, "action"); 

     WithinTransaction<object>(() => 
     { 
      action(); 
      return null; 
     }); 
    } 

    public T WithinTransaction<T>(Func<T> func, IsolationLevel? isolationLevel = null) 
    { 
     Enforce.NotNull(func, "func"); 

     if (Session.Transaction != null && Session.Transaction.IsActive) 
     { 
      return func.Invoke(); 
     } 

     using (var localTran = Session.BeginTransaction(isolationLevel ?? _isolationLevel)) 
     { 
      try 
      { 
       var funcRes = func.Invoke(); 
       localTran.Commit(); 

       return funcRes; 
      } 
      catch (TransactionException ex) 
      { 
       throw new DataException(Resource.TransactionException, ex); 
      } 
      catch (Exception ex) 
      { 
       if (Session.Transaction.IsActive) 
        localTran.Rollback(); 
       throw new DataException(Resource.TransactionException, ex); 
      } 
     } 
    } 

    public bool IsStarted() 
    { 
     return Session.Transaction != null && Session.Transaction.IsActive; 
    } 

    public void Start() 
    { 
     if (Session.Transaction == null || !Session.Transaction.IsActive) 
     { 
      Session.BeginTransaction(_isolationLevel); 
     } 
    } 

    private void Dispose(bool disposing) 
    { 
     if (!disposing || _isDisposed) 
     { 
      return; 
     } 
     _isDisposed = true; 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    #endregion 
} 
+1

請發送郵編。 – Claudius

+1

您用於添加實體的代碼也是必需的,但目前未顯示。 –

+0

它從序列中選擇我的下一個val,但在我的交易中沒有插入,非常奇怪 – Arnaud

回答

3

FlushMode.Never可能是良好的只讀事務,但爲別的,那麼,可能不會。它的xml文檔指出:

除非Flush()被應用程序顯式調用,否則不會刷新ISession。此模式對只讀事務非常有效。

所以不要在默認情況下使用它。
這是我的建議,至少。我知道有一些建議可能會將其用於「表現」的原因,但通過評論此問題來檢查是否仍有問題。
無論如何,我從來沒有首先優化運行時性能,開發人員的表現應該是我認爲的首要任務。 (除非應用程序具有實際的,經過驗證的和相應的運行時性能問題,或者當代碼在運行時執行復雜性方面是一種明顯的編碼恐怖,例如無動機的O(n²)算法或最差)。)

如果您想堅持使用該模式,請在提交事務之前(或按照書面here by Andrew,選擇FlushMode.Commit)在會話上致電Flush。但實際上,這種選擇是開發人員必須使用它的陷阱。

看到默認的模式文檔,Auto

ISession查詢執行之前有時刷新,以確保查詢不會返回已經失效狀態。這是默認的沖洗模式。

是否願意冒着微小的錯誤,因爲在某些數據更改後,在同一會話中發生的查詢中意外地陳舊的數據?

附註:爲什麼「複雜」的代碼與Invoke?見this

+0

非常感謝,我正在尋找所有的交易和會話,但忘記了! – Arnaud

+0

'FlushMode.Auto'有它自己的缺點。不清楚實體何時寫入數據庫,因此NHibernate的沖洗行爲很難預測(即開發人員的性能可能受到不透明沖洗語義的阻礙)。這裏也可以提及'FlushMode.Commit'。 –

+0

在一個事務上下文中,所有東西仍然可以回滾,所以不會有太大的改變。除非開發人員期望在他們的查詢運行在同一會話中時不會考慮到他們的更改,直到他們明確引起刷新。但它更多的是缺乏關於NHibernate的知識問題。現在,如果代碼使用orm查詢和sql查詢的混合,而在查詢之前在同一個會話中進行更改而沒有顯式刷新...那麼,這開始是一個邊緣情況。 (爲了避免「意外」刷新,我們還應該建議不要使用db生成的PK。) –