Mic*_*cah 9 nhibernate design-patterns
我在NHibernate中遇到了ISessions的问题.我一直在"会议结束!" 错误.有人可以告诉我正确的模式,包括以下方法的定义以及何时使用每种方法:
ISession.Close()
ISession.Dispose()
ISession.Disconnect()
Run Code Online (Sandbox Code Playgroud)
这是我的问题.我有一个回调设置来启动一个每隔几分钟向玩家颁发徽章的流程.但是我一直在"会议结束!" 关于无法关联集合的错误或错误.
这是我的存储库:
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
}
Run Code Online (Sandbox Code Playgroud)
这是我的用法.存储库通过Structure Map注入
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();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Aye*_*ien 13
你应该总是使用session.Dispose(); 另一个是非常奇怪的事情
我建议你阅读https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/ISession.cs上的ISession文档
无论如何,当你完成会话时清理的正确方法是处理它(或者更好,用using语句包围使用).在这种情况下,"使用"关闭会话并抑制终结器,即它防止会话对象不必要地幸免于下一次垃圾收集并保存内存.
如果连接已经关闭,则处理它不会引发异常.另一方面,处理后(或关闭后)关闭会引发异常.
文档建议调用disconnect而不是关闭,因为这会释放与连接池的连接.您应该在使用断开连接的会话之前调用重新连接.
根据我的需要,我总是使用"使用"调用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
}
}
Run Code Online (Sandbox Code Playgroud)
我解决这个问题的方法基本上是在这些场景中放弃 NHIbernate 并调用存储过程。无论如何,我认为在我的情况下它的性能更高。
| 归档时间: |
|
| 查看次数: |
25267 次 |
| 最近记录: |