好吧,在我的ASP.NET Webforms应用程序中,我遇到了奇怪的“Session Is Closed”错误,而且是在随机的时间点。然而,今天它终于在同一个地方一遍又一遍地发生。我几乎可以确定在我的代码中没有任何东西正在处理或关闭会话,因为使用会话的代码片段都很好地包含在所有其他代码之外,正如你下面所看到的。
我还使用Ninject作为我的IOC,这可能/可能不重要。
好的,首先是我的SessionFactoryProvider
和SessionProvider
类:
SessionFactoryProvider
public class SessionFactoryProvider : IDisposable
{
ISessionFactory sessionFactory;
public ISessionFactory GetSessionFactory()
{
if (sessionFactory == null)
sessionFactory =
Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(p =>
p.FromConnectionStringWithKey("QoiSqlConnection")))
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<JobMapping>())
.BuildSessionFactory();
return sessionFactory;
}
public void Dispose()
{
if (sessionFactory != null)
sessionFactory.Dispose();
}
}
SessionProvider
public class SessionProvider : IDisposable
{
ISessionFactory sessionFactory;
ISession session;
public SessionProvider(SessionFactoryProvider sessionFactoryProvider)
{
this.sessionFactory = sessionFactoryProvider.GetSessionFactory();
}
public ISession GetCurrentSession()
{
if (session == null)
session = sessionFactory.OpenSession();
return session;
}
public void Dispose()
{
if (session != null)
{
session.Dispose();
}
}
}
这两个类被Ninject连接起来,如下所示: NHibernateModule
public class NHibernateModule : StandardModule
{
public override void Load()
{
Bind<SessionFactoryProvider>().ToSelf().Using<SingletonBehavior>();
Bind<SessionProvider>().ToSelf().Using<OnePerRequestBehavior>();
}
}
据我所知,这些功能都能正常工作。
现在是我的 BaseDao<T>
类:
BaseDao
public class BaseDao<T> : IDao<T> where T : EntityBase
{
private SessionProvider sessionManager;
protected ISession session { get { return sessionManager.GetCurrentSession(); } }
public BaseDao(SessionProvider sessionManager)
{
this.sessionManager = sessionManager;
}
public T GetBy(int id)
{
return session.Get<T>(id);
}
public void Save(T item)
{
using (var transaction = session.BeginTransaction())
{
session.SaveOrUpdate(item);
transaction.Commit();
}
}
public void Delete(T item)
{
using (var transaction = session.BeginTransaction())
{
session.Delete(item);
transaction.Commit();
}
}
public IList<T> GetAll()
{
return session.CreateCriteria<T>().List<T>();
}
public IQueryable<T> Query()
{
return session.Linq<T>();
}
}
这个东西可以像下面这样在Ninject中绑定:
DaoModule
public class DaoModule : StandardModule
{
public override void Load()
{
Bind(typeof(IDao<>)).To(typeof(BaseDao<>))
.Using<OnePerRequestBehavior>();
}
}
现在导致这个问题的网络请求是当我保存一个对象时,直到今天我做了一些模型更改才出现,但是我的模型更改并没有以任何方式改变数据访问代码。尽管它更改了一些NHibernate映射(如果有人感兴趣,我也可以发布这些内容)。
据我所知,在调用BaseDao<SomeClass>.Get
后调用BaseDao<SomeOtherClass>.Get
,然后调用BaseDao<TypeImTryingToSave>.Save
。
就是在Save()
中的第三次调用。
using (var transaction = session.BeginTransaction())
出现“Session is Closed!”错误或异常的故障:
Session is closed!
Object name: 'ISession'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ObjectDisposedException: Session is closed!
Object name: 'ISession'.
实际上,通过调试器可以看到第三次从SessionProvider
请求会话时,它确实已关闭且未连接。
我已验证我的SessionFactoryProvider
和SessionProvider
的Dispose
在请求结束后而不是在Dao进行Save
调用之前被调用。
现在我有点困惑。 有几件事情浮现在脑海中。
- 我是否有任何明显错误?
- NHibernate是否会在我没有要求关闭会话的情况下关闭会话?
- 有什么变通方法或想法吗?
提前致谢。