gpt4 book ai didi

.net - NHibernate 和 ADO.NET 连接池

转载 作者:行者123 更新时间:2023-12-03 12:46:15 25 4
gpt4 key购买 nike

似乎 NHibernate 没有汇集 ADO.NET 数据库连接。只有在事务提交或回滚时才会关闭连接。对源代码的审查表明,无法配置 NHibernate 以便在释放 ISession 时关闭连接。

这种行为的意图是什么? ADO.NET 本身具有连接池。没有必要在事务中一直保持它们打开。使用这种行为也会创建不必要的分布式事务。 http://davybrion.com/blog/2010/05/avoiding-leaking-connections-with-nhibernate-and-transactionscope/ 中描述的一种可能的解决方法因此不起作用(至少不适用于 NHibernate 3.1.0)。我正在使用 Informix。每个其他数据库(NHibernate Connection Pooling)似乎都存在同样的问题。

是否有任何其他解决方法或建议可以避免此问题?

这是一个重现问题的单元测试:

  [Test]
public void DoesNotCloseConnection()
{
using (SessionFactoryCache sessionFactoryCache = new SessionFactoryCache())
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TimeSpan.FromMinutes(10) }))
{
fixture.Setup(); // Creates test data

System.Data.IDbConnection connectionOne;
System.Data.IDbConnection connectionTwo;

using (ISessionFactory sessionFactory = sessionFactoryCache.CreateFactory(GetType(), new TestNHibernateConfigurator()))
{
using (ISession session = sessionFactory.OpenSession())
{
var result = session.QueryOver<Library>().List<Library>();
connectionOne = session.Connection;
}
}

// At this point the first IDbConnection used internally by NHibernate should be closed

using (ISessionFactory sessionFactory = sessionFactoryCache.CreateFactory(GetType(), new TestNHibernateConfigurator()))
{
using (ISession session = sessionFactory.OpenSession())
{
var result = session.QueryOver<Library>().List<Library>();
connectionTwo = session.Connection;
}
}

// At this point the second IDbConnection used internally by NHibernate should be closed

// Now two connections are open because the transaction is still running
Assert.That(connectionOne.State, Is.EqualTo(System.Data.ConnectionState.Closed)); // Fails because State is still 'Open'
Assert.That(connectionTwo.State, Is.EqualTo(System.Data.ConnectionState.Closed)); // Fails because State is still 'Open'
}
}
}

NHibernate-Session 的处理没有任何作用,因为我们仍在事务中

SessionImpl.cs:
public void Dispose()
{
using (new SessionIdLoggingContext(SessionId))
{
log.Debug(string.Format("[session-id={0}] running ISession.Dispose()", SessionId));
if (TransactionContext!=null)
{
TransactionContext.ShouldCloseSessionOnDistributedTransactionCompleted = true;
return;
}
Dispose(true);
}
}

注入(inject)自定义 ConnectionProvider 也将不起作用,因为调用 ConnectionProvider 的 ConnectionManager 有几个前提条件,检查不允许在事务中关闭连接。

连接管理器.cs:
public IDbConnection Disconnect() {
if (IsInActiveTransaction)
throw new InvalidOperationException("Disconnect cannot be called while a transaction is in progress.");

try
{
if (!ownConnection)
{
return DisconnectSuppliedConnection();
}
else
{
DisconnectOwnConnection();
ownConnection = false;
return null;
}
}
finally
{
// Ensure that AfterTransactionCompletion gets called since
// it takes care of the locks and cache.
if (!IsInActiveTransaction)
{
// We don't know the state of the transaction
session.AfterTransactionCompletion(false, null);
}
}
}

最佳答案

NHibernate 有两种“模式”。

  • 您可以在应用程序中打开连接,然后由应用程序来管理它。在将连接传递到 sessionfactory.OpenSession(connection) 时使用此“模式”。 .
  • 或者连接是由 NH 创建的。然后在 session 关闭时关闭。此“模式”在未将连接传递到 sessionfactory.OpenSession() 时使用。

  • TransactionScope 有一些支持.它最有可能使用第一个“模式”。可能连接不是由 NH 持有,而是由事务范围持有。我不确切知道,我不使用环境事务。

    顺便说一下,NH 正在使用 ADO.NET 连接池。

    您也可以使用 ISession.Disconnect() 断开 session 。并使用 ISession.Reconnect() 重新连接.

    documentation你发现:

    The method ISession.Disconnect() will disconnect the session from the ADO.NET connection and return the connection to the pool (unless you provided the connection).

    关于.net - NHibernate 和 ADO.NET 连接池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7567233/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com