gpt4 book ai didi

c# - NHibernate 和奇数 "Session is Closed!"错误

转载 作者:IT王子 更新时间:2023-10-29 04:48:28 25 4
gpt4 key购买 nike

注意:既然我已经输入了这个,我不得不为这个超长的问题道歉,但是,我认为这里提供的所有代码和信息在某种程度上都是相关的。


好的,我在我的 ASP.NET webforms 应用程序中随机出现奇怪的“Session Is Closed”错误。然而,今天,它终于一次又一次地发生在同一个地方。我几乎可以肯定,我的代码中没有处理或关闭 session ,因为使用的代码位与所有其他代码完全分开,如下所示。

我也在使用 ninject 作为我的 IOC,这可能/可能不重要。

好的,所以,首先是我的 SessionFactoryProviderSessionProvider类:


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 中绑定(bind):


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 已关闭!”或者更确切地说是异常(exception):

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 请求 session 它确实是关闭的,没有连接。

我已验证 Dispose在我的 SessionFactoryProvider在我的 SessionProvider 上在请求结束时调用,而不是在 Save 之前调用在我的 Dao 上进行调用。

所以现在我有点卡住了。我想到了一些事情。

  • 我做错了什么吗?
  • NHibernate 是否会在我不要求的情况下关闭 session ?
  • 关于我可以做什么的任何解决方法或想法?

提前致谢

最佳答案

ASP.NET 是多线程的,因此对 ISession 的访问必须是线程安全的。假设您正在使用每次请求 session ,最简单的方法是使用 NHibernate 的内置处理 contextual sessions .

首先配置 NHibernate 以使用 web session 上下文类:

sessionFactory = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(p =>
p.FromConnectionStringWithKey("QoiSqlConnection")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<JobMapping>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web")
.BuildSessionFactory();

然后使用 ISessionFactory.GetCurrentSession() 获取现有 session ,如果不存在,则将新 session 绑定(bind)到工厂。下面我将剪切和粘贴用于打开和关闭 session 的代码。

    public ISession GetContextSession()
{
var factory = GetFactory(); // GetFactory returns an ISessionFactory in my helper class
ISession session;
if (CurrentSessionContext.HasBind(factory))
{
session = factory.GetCurrentSession();
}
else
{
session = factory.OpenSession();
CurrentSessionContext.Bind(session);
}
return session;
}

public void EndContextSession()
{
var factory = GetFactory();
var session = CurrentSessionContext.Unbind(factory);
if (session != null && session.IsOpen)
{
try
{
if (session.Transaction != null && session.Transaction.IsActive)
{
session.Transaction.Rollback();
throw new Exception("Rolling back uncommited NHibernate transaction.");
}
session.Flush();
}
catch (Exception ex)
{
log.Error("SessionKey.EndContextSession", ex);
throw;
}
finally
{
session.Close();
session.Dispose();
}
}
}

关于c# - NHibernate 和奇数 "Session is Closed!"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2572015/

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