2015-01-14 72 views
1

通常它工作正常,但在某些情況下(我不能複製)我收到的NullReferenceException與堆棧跟蹤:NullReference與交易處置會話時

 

    at Npgsql.NpgsqlCommand.ClearPoolAndCreateException(Exception e) in C:\projects\Npgsql2\src\Npgsql\NpgsqlCommand.cs:line 1505 
    at Npgsql.NpgsqlCommand.GetReader(CommandBehavior cb) in C:\projects\Npgsql2\src\Npgsql\NpgsqlCommand.cs:line 650 
    at Npgsql.NpgsqlCommand.ExecuteBlind() in C:\projects\Npgsql2\src\Npgsql\NpgsqlCommand.cs:line 499 
    at Npgsql.NpgsqlTransaction.Rollback() in C:\projects\Npgsql2\src\Npgsql\NpgsqlTransaction.cs:line 185 
    at Npgsql.NpgsqlTransaction.Dispose(Boolean disposing) in C:\projects\Npgsql2\src\Npgsql\NpgsqlTransaction.cs:line 141 
    at NHibernate.Transaction.AdoTransaction.Dispose(Boolean isDisposing) in p:\nhibernate-core\src\NHibernate\Transaction\AdoTransaction.cs:line 368 
    at NHibernate.Impl.SessionImpl.Close() in p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 380 
    at NHibernate.Impl.SessionImpl.Dispose(Boolean isDisposing) in p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1738 
    at NHibernate.Impl.SessionImpl.Dispose() in p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1709 
public virtual IEnumerable<User.PublishedInfo> GetUsersByXP(int count) 
    { 
     using (ISession session = SessionFactory.OpenSession()) 
     { 
      using (session.BeginTransaction()) 
      { 
       var result = session.CreateCriteria<User>() 
        .SetProjection(PublishedUserProjections) 
        .AddOrder(Order.Desc("XP")) 
        .SetMaxResults(count) 
        .SetResultTransformer(Transformers.AliasToBean<User.PublishedInfo>()) 
        .List<User.PublishedInfo>(); 

       foreach (var r in result) 
        r.Initialize(); 

       session.Transaction.Commit(); 

       return result; // this line 
      } 
     } 
    } 

什麼可以可能錯在這裏?

UPDATE

有時在相同的代碼片段(但在調用BeginTransaction)我收到一個異常「超時而獲取連接」。也許這有點相關。

+0

難道是因爲有時會話中的事務並沒有完全初始化,然後''使用''塊與'session.BeginTransaction()'裏面試圖處置一些實際上不存在的東西?簡而言之,我會嘗試初始化此塊中的事務變量,並僅在它不爲空時才提交它。此外,當發生交易事件以外的錯誤時會發生什麼?我無法在任何地方看到任何回滾... –

+0

@WillMarcouiller「發生交易事件之外的錯誤時會發生什麼?」我不在乎,因爲只有閱讀操作。 「有時候會話中的事務根本沒有初始化」 - 比在進入使用塊之前應該拋出異常。 「只有當它不爲空時才提交它。」 NullReference不在我的代碼中。它在調用ISession.Dispose時拋出。 – Vlad

+0

我明白了。但是,如果只讀取,爲什麼首先調用'BeginTransaction'方法?如果我相信該方法的名稱,我將它作爲'GetUsersByXP'說,它只從底層數據庫讀取。這裏沒有必要進行交易。此外,練習是分配一個變量,該變量將被放置在使用塊中,然後.NET知道要處理什麼。在這裏,正如我所看到的那樣,我猜測自從調用'BeginTransaction'方法以來,在處理會話時會出現某種混淆,並且沒有特別引用該事務。 –

回答

1

我在2.0.14.3中看到了同樣的東西。你正在運行哪個版本?和哪個版本的NHibernate?

通過代碼看,我看到

internal NpgsqlException ClearPoolAndCreateException(Exception e) 
    { 
     Connection.ClearPool(); 
     return new NpgsqlException(resman.GetString("Exception_ConnectionBroken"), e); 
    } 

2.2似乎來自同一

而大多數其他的操作總是在連接屬性空校驗挨。這可能是一個錯誤,但它似乎也被重寫在主分支中。

唯一的來源,我可以找到實際將內部連接設置爲null(除非它由NHibernate完成,但我懷疑它)將是如果NpgsqlCommand將被丟棄,然後從NpgsqlDataReader中讀取。

編輯:

據源,該回滾將在處置調用如果NpgsqlTransaction仍然有一個連接,並具有活性的事務。在你的情況下,Commit應該將它設置爲null。事實上,在你的使用塊中使用session.Transaction(與存儲從BeginTransaction()調用返回的引用相反)可能是罪魁禍首,因爲如果會話中沒有會話,調用session.Transaction會隱式地創建一個事務。這可能會導致提交調用實際上只是提交一個空的事務,然後Dispose將在用BeginTransaction創建的事務上被調用。

在代碼運行時,您是否有可能正在使用會話的多線程或異步代碼?

+0

它根本不應該調用Rollback(請參閱我的stracktrace),因爲事務已經提交。 – Vlad

+0

我使用3.3.1.4000 – Vlad

+0

Se編輯。和哪個版本的Npgsql? – jishi

0

聽起來對我來說,如果在事務內部發生了一些錯誤,它會拋出一個異常,它會處理會話/事務。試試...

using (ISession session = SessionFactory.OpenSession()) 
    { 
     List<User.PublishedInfo> results = null; 
     ITransaction transaction = null; 
     try 
     { 
      transaction = session.BeginTransaction(); 
      results = session.CreateCriteria<User>() 
       .SetProjection(PublishedUserProjections) 
       .AddOrder(Order.Desc("XP")) 
       .SetMaxResults(count) 
       .SetResultTransformer(Transformers.AliasToBean<User.PublishedInfo>()) 
       .List<User.PublishedInfo>(); 

      foreach (var r in results) 
       r.Initialize(); 

      transaction.Commit(); 
     } 
     catch(Exceptionn ex) 
     { 
      if (transaction != null) 
       transaction.Rollback(); 
      throw; 
     } 
     return results; 
    } 
+0

我加了「throw new Exception();」我的代碼之前transaction.Commit()但我不能repro NullReferenceException。 – Vlad