在 NHibernate 中达到连接池限制
Connection Pool Limit reached in NHibernate
我在尝试为使用 NHibernate 的 MVC 应用程序正确处理我的工作单元的生命周期时遇到问题(认为这是我的 UoW 的问题)。多线程有机会,因此它也需要考虑到这一点。我决定尝试让 NHibernate 管理连接,而不是在我的依赖注入器 (StructureMap) 中进行管理,但现在我遇到了连接池限制已达到的问题。
为了发布代码,我已经简化了其中的一些内容,但希望它能帮助您了解我遗漏了什么...
NHibernate 配置
var cfg = new Configuration()
.DataBaseIntegration(x =>
{
x.ConnectionStringName = "ApplicationConnectionStringName";
x.Dialect<CustomMsSql2008Dialect>(); //Inherits from MsSql2008GeographyDialect
x.IsolationLevel = IsolationLevel.RepeatableRead;
x.BatchSize = 100;
})
.CurrentSessionContext<WebSessionContext>()
.Cache(c =>
{
c.Provider<SysCacheProvider>();
c.UseQueryCache = true;
});
工作单元
public class NHibernateUnitOfWork : INHibernateUnitOfWork
{
private ITransaction transaction;
private bool isDisposed;
private readonly ISessionFactory source;
public NHibernateUnitOfWork(ISessionFactory source)
{
this.source = source;
VerifyIsNotDisposed();
if (CurrentSessionContext.HasBind(source))
{
CurrentSession = source.GetCurrentSession();
this.transaction = CurrentSession.Transaction;
}
else
{
CurrentSession = this.source.OpenSession();
CurrentSessionContext.Bind(CurrentSession);
BeginNewTransaction();
}
}
public ISession CurrentSession { get; private set; }
public void Commit()
{
VerifyIsNotDisposed();
this.transaction.Commit();
BeginNewTransaction();
}
private void BeginNewTransaction()
{
if (this.transaction != null)
{
this.transaction.Dispose();
}
this.transaction = CurrentSession.BeginTransaction();
}
public void Rollback()
{
VerifyIsNotDisposed();
this.transaction.Rollback();
BeginNewTransaction();
}
private void VerifyIsNotDisposed()
{
if (this.isDisposed) throw new ObjectDisposedException(GetType().Name);
}
public void Dispose()
{
if (this.isDisposed) return;
this.transaction.Dispose();
CurrentSessionContext.Unbind(this.source);
CurrentSession.Dispose();
this.isDisposed = true;
}
}
通过 StructureMap 请求开始和结束处理程序
public class StructureMapScopeModule : IHttpModule {
public void Dispose() {
}
public void Init(HttpApplication context) {
context.BeginRequest += (sender, e) =>
{
StructuremapMvc.StructureMapDependencyScope.CreateChildContainer();
var unitOfWork = StructuremapMvc.StructureMapDependencyScope.Container.GetInstance<IUnitOfWork>();
};
context.EndRequest += (sender, e) => {
var unitOfWork = StructuremapMvc.StructureMapDependencyScope.Container.GetInstance<IUnitOfWork>();
unitOfWork.Commit();
HttpContextLifecycle.DisposeAndClearAll();
StructuremapMvc.StructureMapDependencyScope.DisposeChildContainer();
};
}
}
运行 现在获取连接计数的查询给出了将近 125 个连接。
请关闭所有打开的连接,这通常是达到池限制的原因...
正确实现 IDisposable 并不像看起来那么简单...下面是我正在使用的示例实现(从 SO 的答案中复制)
using System;
namespace AlgoSys.Common.SharedUtils
{
public abstract class Disposable : IDisposable
{
private bool _disposed;
// Dispose() calls Dispose(true)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources itself, but leave the other methods
// exactly as they are.
~Disposable()
{
// Finalizer calls Dispose(false)
Dispose(false);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
if(_disposed) return;
if (disposing)
{
OnDispose();
}
_disposed = true;
}
protected abstract void OnDispose();
}
}
太好了,您在发表评论之前对其进行了测试...将评论作为答案。
我在尝试为使用 NHibernate 的 MVC 应用程序正确处理我的工作单元的生命周期时遇到问题(认为这是我的 UoW 的问题)。多线程有机会,因此它也需要考虑到这一点。我决定尝试让 NHibernate 管理连接,而不是在我的依赖注入器 (StructureMap) 中进行管理,但现在我遇到了连接池限制已达到的问题。
为了发布代码,我已经简化了其中的一些内容,但希望它能帮助您了解我遗漏了什么...
NHibernate 配置
var cfg = new Configuration()
.DataBaseIntegration(x =>
{
x.ConnectionStringName = "ApplicationConnectionStringName";
x.Dialect<CustomMsSql2008Dialect>(); //Inherits from MsSql2008GeographyDialect
x.IsolationLevel = IsolationLevel.RepeatableRead;
x.BatchSize = 100;
})
.CurrentSessionContext<WebSessionContext>()
.Cache(c =>
{
c.Provider<SysCacheProvider>();
c.UseQueryCache = true;
});
工作单元
public class NHibernateUnitOfWork : INHibernateUnitOfWork
{
private ITransaction transaction;
private bool isDisposed;
private readonly ISessionFactory source;
public NHibernateUnitOfWork(ISessionFactory source)
{
this.source = source;
VerifyIsNotDisposed();
if (CurrentSessionContext.HasBind(source))
{
CurrentSession = source.GetCurrentSession();
this.transaction = CurrentSession.Transaction;
}
else
{
CurrentSession = this.source.OpenSession();
CurrentSessionContext.Bind(CurrentSession);
BeginNewTransaction();
}
}
public ISession CurrentSession { get; private set; }
public void Commit()
{
VerifyIsNotDisposed();
this.transaction.Commit();
BeginNewTransaction();
}
private void BeginNewTransaction()
{
if (this.transaction != null)
{
this.transaction.Dispose();
}
this.transaction = CurrentSession.BeginTransaction();
}
public void Rollback()
{
VerifyIsNotDisposed();
this.transaction.Rollback();
BeginNewTransaction();
}
private void VerifyIsNotDisposed()
{
if (this.isDisposed) throw new ObjectDisposedException(GetType().Name);
}
public void Dispose()
{
if (this.isDisposed) return;
this.transaction.Dispose();
CurrentSessionContext.Unbind(this.source);
CurrentSession.Dispose();
this.isDisposed = true;
}
}
通过 StructureMap 请求开始和结束处理程序
public class StructureMapScopeModule : IHttpModule {
public void Dispose() {
}
public void Init(HttpApplication context) {
context.BeginRequest += (sender, e) =>
{
StructuremapMvc.StructureMapDependencyScope.CreateChildContainer();
var unitOfWork = StructuremapMvc.StructureMapDependencyScope.Container.GetInstance<IUnitOfWork>();
};
context.EndRequest += (sender, e) => {
var unitOfWork = StructuremapMvc.StructureMapDependencyScope.Container.GetInstance<IUnitOfWork>();
unitOfWork.Commit();
HttpContextLifecycle.DisposeAndClearAll();
StructuremapMvc.StructureMapDependencyScope.DisposeChildContainer();
};
}
}
运行 现在获取连接计数的查询给出了将近 125 个连接。
请关闭所有打开的连接,这通常是达到池限制的原因...
正确实现 IDisposable 并不像看起来那么简单...下面是我正在使用的示例实现(从 SO 的答案中复制)
using System;
namespace AlgoSys.Common.SharedUtils
{
public abstract class Disposable : IDisposable
{
private bool _disposed;
// Dispose() calls Dispose(true)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources itself, but leave the other methods
// exactly as they are.
~Disposable()
{
// Finalizer calls Dispose(false)
Dispose(false);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
if(_disposed) return;
if (disposing)
{
OnDispose();
}
_disposed = true;
}
protected abstract void OnDispose();
}
}
太好了,您在发表评论之前对其进行了测试...将评论作为答案。