Reputation: 3181
Usually it works fine but in some conditions (I can't reproduce it) I receive NullReferenceException with stacktrace:
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
}
}
}
What can be possible wrong here?
UPDATE
Sometimes in the same code fragment (but in BeginTransaction) I receive an exception "Timeout while getting a connection". Perhaps this is somehow related.
Upvotes: 1
Views: 1563
Reputation: 24634
I'm seeing the same thing in 2.0.14.3. Which version are you running? And which version of NHibernate?
Looking through the code, I see that
internal NpgsqlException ClearPoolAndCreateException(Exception e)
{
Connection.ClearPool();
return new NpgsqlException(resman.GetString("Exception_ConnectionBroken"), e);
}
2.2 seems to suffer from the same
Where as most other operations always make a null check on Connection property. This might be a bug, but it also seem to be rewritten heavily in the master branch.
The only source that I can find that would actually set the connection to null internally (unless it is somehow done by NHibernate but I doubt it) would be if the NpgsqlCommand would be disposed and then read from the NpgsqlDataReader.
EDIT:
According to the source, the Rollback will be invoked on Dispose if the NpgsqlTransaction still has a connection and a transaction active. In your case, the Commit should have set it as null. The fact that you are using session.Transaction in your using block (opposed to storing the reference returned from your BeginTransaction() call) might be the culprit, since a call to session.Transaction implicitly creates a transaction if none is present in your session. This could cause the commit call to actually just commit on an empty transaction, and then the Dispose would be invoked on the transaction that was created with BeginTransaction.
Do you have any multi-threading or asynchronous code that might be working with your session while this code is running?
Upvotes: 1
Reputation: 6054
Sounds to me like, if some error occurred inside the transaction, it would throw an exception and it would dispose the session/transaction. Try...
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;
}
Upvotes: 0