如何正确使用NHibernate会话对象-会话已关闭!错误
我在NHibernate遇到了一些问题。我一直在关门!错误。请告诉我正确的模式,包括以下方法的定义,以及何时使用这些方法:如何正确使用NHibernate会话对象-会话已关闭!错误,nhibernate,design-patterns,Nhibernate,Design Patterns,我在NHibernate遇到了一些问题。我一直在关门!错误。请告诉我正确的模式,包括以下方法的定义,以及何时使用这些方法: ISession.Close() ISession.Dispose() ISession.Disconnect() 这是我的问题。我有一个回调设置来启动一个进程,每隔几分钟给玩家颁发一次徽章。然而,我总是让会议关闭!错误或关于无法关联集合的错误 这是我的存储库: public class NHibernateRepository : IRepository { #regi
ISession.Close()
ISession.Dispose()
ISession.Disconnect()
这是我的问题。我有一个回调设置来启动一个进程,每隔几分钟给玩家颁发一次徽章。然而,我总是让会议关闭!错误或关于无法关联集合的错误
这是我的存储库:
public class NHibernateRepository : IRepository
{
#region Fields
private ISession _session;
private readonly ISessionFactory _sessionFactory;
#endregion
#region Constructors
public NHibernateRepository(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
#endregion
#region IRepository Implementation
public ISession OpenSession()
{
_session = _sessionFactory.OpenSession();
return _session;
}
public IQueryable<TModel> All<TModel>()
{
return _session.Linq<TModel>();
}
public void Save<TModel>(TModel model)
{
_session.Save(model);
}
public void Update<TModel>(TModel model)
{
_session.Update(model);
}
public void Delete<TModel>(TModel model)
{
_session.Delete(model);
}
public ITransaction BeginTransaction()
{
return _session.BeginTransaction();
}
public void Flush()
{
_session.Flush();
}
#endregion
}
这是我的用法。存储库是通过结构图注入的
private Object _awardBadgesLock = new object(); //In case the callback happens again before the previous one completes
public void AwardBadges()
{
lock (_awardBadgesLock)
{
using(session = _repository.OpenSession())
{
foreach (var user in _repository.All<User>().ToList())
{
var userPuzzles = _repository.All<Puzzle>().ByUser(user.Id).ToList();
var userVotes = _repository.All<Vote>().Where(x => x.UserId == user.Id).ToList();
var userSolutions = _repository.All<Solution>().ByUser(user.Id).ToList().Where(x => !userPuzzles.Select(y => y.Id).Contains(x.PuzzleId));
var ledPuzzles = GetPuzzlesLedByUser(user.Id);
AwardPlayerBadge(user, userSolutions);
AwardCriticBadge(user, userVotes);
AwardCreatorBadge(user, userPuzzles);
AwardRidlerBadge(user, userPuzzles);
AwardSupporterBadge(user, userVotes);
AwardPopularBadge(user, userPuzzles);
AwardNotableBadge(user, userPuzzles);
AwardFamousBadge(user, userPuzzles);
AwardLeaderBadge(user, ledPuzzles);
using (var tx = _repository.BeginTransaction())
{
_repository.Update(user);
tx.Commit();
}
}
}
}
}
您应该始终使用session.Dispose;
另一个是针对非常奇怪的事件我建议您阅读上的ISession文档 无论如何,当您完成会话时,正确的清理方法是处置它,或者更好地使用using语句来围绕用法。在这种情况下,使用将关闭会话并抑制终结器,即,它将防止会话对象在下一次垃圾收集中不必要地存活下来,并保存内存 如果连接已关闭,则处理它不会引发异常。另一方面,在处理或关闭后关闭会引发异常 文档建议调用disconnect而不是Close,因为这会释放到连接池的连接。在使用断开连接的会话之前,应先调用Reconnect
出于我的需要,我总是使用which调用Dispose,从来没有使用过其他两个函数。问题在于ISession不是线程安全的。在单独的线程上激发了多个方法,这些线程都创建了ISession实例。问题在于他们都共享同一个SessionFactory。映像这两种方法都在单独的线程上触发:
ISessionFactory _sessionFactory;
void MethodOne()
{
using(ISession session = _sessionFactory.OpenSession())
{
//Do something with really quick with the session
//Then dispose of it
}
}
void MethodTwo()
{
//OpenSession() actually returns the same instance used in the
//previous method that has already disposed of the object;
using(ISession session = _sessionFactory.OpenSession())
{
//Do something with a session that has already been disposed
//throws errors
}
}
我是如何修复的,基本上是在这些场景中抛弃NHIbernate,而是调用存储过程。无论如何,我认为在我的情况下,它的性能更高。关于这个问题,只要您处理了会话,您的锁定方法是正确的,但可能错误存在于代码的另一部分之下。顺便说一下,由于会话的工作单元实现和聚合根的事务,因此最好将会话变量传递给存储库,如下所示:
using (ISession session = SessionFactory.OpenSession())
{
Repository1 rep1 = new Repository1(session);
Repository2 rep1 = new Repository2(session);
Repository3 rep1 = new Repository3(session);
// some logics
using (var tx = session.BeginTransaction())
tx.Commit();
}
。
.
.我正在使用调用dispose的using语句。但我仍然会犯错误,而且这种情况并非总是发生。只是有些时候。是的,我是一个web应用程序,但我没有将NHibernate会话与web会话集成。这个存储库在其他地方使用吗?因为,另一个OpenSession调用将丢失第一个。但他正在使用“using”不是吗。。。usingsession=\u repository.OpenSessionInteresting-您使用的是哪个ISessionFactory实现?他们说实现者必须是线程安全的。这正是问题所在。实现者必须是线程安全的,因为SessionFactory不是线程安全的。对,但哪个具体的ISessionFactory实现?SessionFactoryImpl?我相信如果你能重现这个问题,或者更好的是,找到bug,NHibernate团队会有兴趣听到它。Micah,这让我很困惑:我真的认为SessionFactory是线程安全的,根据NHibernate文档:ISessionFactory是一个昂贵的创建,要由所有应用程序线程共享的线程安全对象。我将继续我的项目,假设这是真的,您或者使用了错误的实现,或者错误存在于其他地方。