使用 NHibernate Castle 设施进行延迟加载
我是否必须关闭 Castle 的 ISessionManager
为 NHibernate 生成的 ISession
? 我如何处理这些 ISession
的事务? 我对 NHibernate 还是很陌生。
编辑:我想要延迟加载,但收到此消息:
初始化[懒惰地失败 初始化角色集合: , 否 会话或会话已关闭”
这是我的通用存储库,我继承它来实现特定实例。
[Transactional]
public class Repository<TKey, TModel>
: IRepository<TKey, TModel>
where TKey : IComparable
where TModel : class
{
private readonly ISessionManager _sessionManager;
protected ISession Session { get { return _sessionManager.OpenSession(); } }
public Repository(ISessionManager sessionManager)
{
_sessionManager = sessionManager;
}
#region IRepository<TKey,TModel> Members
public virtual TModel Select(TKey key)
{
using (var session = _sessionManager.OpenSession())
{
return session.Get<TModel>(key);
}
}
public virtual IList<TModel> SelectWhere(Func<TModel, bool> query)
{
using (var session = Session)
{
return session.Linq<TModel>().Where(query).ToList();
}
}
public virtual TModel Single(Func<TModel, bool> query)
{
using (var session = Session)
{
return session.Linq<TModel>().SingleOrDefault(query);
}
}
public virtual TModel First(Func<TModel, bool> query)
{
using (var session = Session)
{
return session.Linq<TModel>().FirstOrDefault(query);
}
}
public virtual IList<TModel> All()
{
using (var session = Session)
{
return session.Linq<TModel>().ToList();
}
}
[Transaction(TransactionMode.Requires)]
public virtual void Store(TModel entity)
{
using (var session = Session)
{
session.SaveOrUpdate(entity);
}
}
[Transaction(TransactionMode.Requires)]
public virtual void Store(IEnumerable<TModel> entities)
{
using (var session = Session)
{
foreach (TModel entity in entities)
session.SaveOrUpdate(entity);
}
}
[Transaction(TransactionMode.Requires)]
public virtual void Remove(TModel entity)
{
using (var session = Session)
{
session.Delete(entity);
}
}
public virtual void Remove(Func<TModel, bool> query)
{
IEnumerable<TModel> entities = SelectWhere(query);
Remove(entities);
}
[Transaction(TransactionMode.Requires)]
public virtual void Remove(IEnumerable<TModel> entities)
{
using (var session = Session)
{
foreach (TModel entity in entities)
session.Delete(entity);
}
}
#endregion
}
public class Repository<TModel>
: Repository<Guid, TModel>, IRepository<TModel>
where TModel : class
{
public Repository(ISessionManager sessionManager) : base(sessionManager) { }
}
public class Repository
: Repository<ulong, object>, IRepository
{
public Repository(ISessionManager sessionManager) : base(sessionManager) { }
}
这是该存储库的调用示例:
IUserRepository userRepository = new UserRepository(); // This is actually provided by my IoC
var users = userRepository.All();
foreach (var user in Users)
{
foreach (var picture in user.Pictures)
{
// I get exceptions when I do stuff like this.
}
}
Do I have to close the ISession
's that are generated by Castle's ISessionManager
for NHibernate? How do I handle transactions with those ISession
's? I'm still quite new to NHibernate.
Edit: I would like to have lazy loading but I get this message:
Initializing[failed to lazily
initialize a collection of role: , no
session or session was closed"
Here is my generic Repository which I inherit to implement specific instances.
[Transactional]
public class Repository<TKey, TModel>
: IRepository<TKey, TModel>
where TKey : IComparable
where TModel : class
{
private readonly ISessionManager _sessionManager;
protected ISession Session { get { return _sessionManager.OpenSession(); } }
public Repository(ISessionManager sessionManager)
{
_sessionManager = sessionManager;
}
#region IRepository<TKey,TModel> Members
public virtual TModel Select(TKey key)
{
using (var session = _sessionManager.OpenSession())
{
return session.Get<TModel>(key);
}
}
public virtual IList<TModel> SelectWhere(Func<TModel, bool> query)
{
using (var session = Session)
{
return session.Linq<TModel>().Where(query).ToList();
}
}
public virtual TModel Single(Func<TModel, bool> query)
{
using (var session = Session)
{
return session.Linq<TModel>().SingleOrDefault(query);
}
}
public virtual TModel First(Func<TModel, bool> query)
{
using (var session = Session)
{
return session.Linq<TModel>().FirstOrDefault(query);
}
}
public virtual IList<TModel> All()
{
using (var session = Session)
{
return session.Linq<TModel>().ToList();
}
}
[Transaction(TransactionMode.Requires)]
public virtual void Store(TModel entity)
{
using (var session = Session)
{
session.SaveOrUpdate(entity);
}
}
[Transaction(TransactionMode.Requires)]
public virtual void Store(IEnumerable<TModel> entities)
{
using (var session = Session)
{
foreach (TModel entity in entities)
session.SaveOrUpdate(entity);
}
}
[Transaction(TransactionMode.Requires)]
public virtual void Remove(TModel entity)
{
using (var session = Session)
{
session.Delete(entity);
}
}
public virtual void Remove(Func<TModel, bool> query)
{
IEnumerable<TModel> entities = SelectWhere(query);
Remove(entities);
}
[Transaction(TransactionMode.Requires)]
public virtual void Remove(IEnumerable<TModel> entities)
{
using (var session = Session)
{
foreach (TModel entity in entities)
session.Delete(entity);
}
}
#endregion
}
public class Repository<TModel>
: Repository<Guid, TModel>, IRepository<TModel>
where TModel : class
{
public Repository(ISessionManager sessionManager) : base(sessionManager) { }
}
public class Repository
: Repository<ulong, object>, IRepository
{
public Repository(ISessionManager sessionManager) : base(sessionManager) { }
}
Here is a sample invoking of that repository:
IUserRepository userRepository = new UserRepository(); // This is actually provided by my IoC
var users = userRepository.All();
foreach (var user in Users)
{
foreach (var picture in user.Pictures)
{
// I get exceptions when I do stuff like this.
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,始终处置
ISession
。 请参阅有关ISessionManager
用法的文档< /a>.对于交易,请考虑使用自动交易工具。
SessionManager 是 ATM 感知的,因此它将处理 < code>ISession 在需要时巧妙地考虑事务,即使您显然已经处理了
ISession
。这里有一个快速指南 使用 ASP.NET MVC + Castle 自动事务设施 + NHibernate 设施的脏示例应用程序
Yes, always dispose the
ISession
. See the docs onISessionManager
usage.For transactions, consider using the Automatic Transaction Facility.
The SessionManager is ATM-aware so it will dispose the
ISession
smartly when it needs to, taking transactions into account, even when you apparently have disposed theISession
.Here's a quick & dirty sample app that uses ASP.NET MVC + Castle Automatic Transaction Facility + NHibernate facility
我们使用带有 using 语句的事务来处理处置。
如果我在同一操作中进行修改后访问对象,我仍然会收到延迟加载错误。 我已通过保存后不访问对象来修复该错误。 这是一个解释: NHibernate.LazyInitializationException
我相信这是由于没有正确保存层次结构造成的。 我还没有测试过它,但如果您想访问父对象,也许保存它们可以解决问题。 只需将保存后需要访问的信息放入保存前的局部变量中似乎就可以解决我的问题。
We use transactions with using statements to handle the disposing.
I will still get the lazy loading error if I am accessing objects after making a modification in the same action. I have fixed the error by not accessing the objects after a save. Here's an explination: NHibernate.LazyInitializationException
I believe it is due to not saving the hierarchy correctly. I haven't tested it, but maybe saving the parent objects if you wish to access them will fix the issue. Simply putting the information I needed to access after the save into local variables before the save seemed to correct my issue.