通常它工作正常,但在某些情况下(我无法重现)我收到了堆栈跟踪的NullReferenceException:
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
}
}
}
这里可能出现什么问题?
更新
有时在相同的代码片段中(但在BeginTransaction中)我收到异常&#34;在获取连接时超时#34;。也许这在某种程度上是相关的。
答案 0 :(得分:1)
我在2.0.14.3中看到了同样的事情。你正在运行哪个版本?那个版本的NHibernate?
查看代码,我看到了
internal NpgsqlException ClearPoolAndCreateException(Exception e)
{
Connection.ClearPool();
return new NpgsqlException(resman.GetString("Exception_ConnectionBroken"), e);
}
2.2似乎受到同样的影响
大多数其他操作总是对Connection属性进行空检查。这可能是一个错误,但它似乎也在主分支中被大量重写。
我能找到的唯一内部实际上会在内部将连接设置为null(除非它以某种方式由NHibernate完成,但我怀疑它)将是NpgsqlCommand将被处理然后从NpgsqlDataReader读取。
编辑:
根据源代码,如果NpgsqlTransaction仍有连接且事务处于活动状态,则将在Dispose上调用Rollback。在您的情况下,Commit应该将其设置为null。您在使用块中使用session.Transaction(与存储从BeginTransaction()调用返回的引用相反的事实)可能是罪魁祸首,因为如果会话中没有事件,则调用session.Transaction会隐式创建事务。 。这可能导致提交调用实际上只是对空事务进行提交,然后将在使用BeginTransaction创建的事务上调用Dispose。
在此代码运行时,您是否有可能与会话一起使用的多线程或异步代码?
答案 1 :(得分: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;
}