请参阅以下代码:
public Enquiry GetByID(Guid personID)
{
using (IUnitOfWork<ISession> unitOfWork = UnitOfWorkFactory.Create())
{
IRepository repository = RepostioryFactory.Create(unitOfWork);
var Person = repository.GetById(personID);
return Person;
}
}
它包含在应用程序服务层中。 Person被传递回Controller并加载到视图中。视图然后出错,因为它无法加载Person.Collection(列表)。
我相信这是因为使用延迟加载加载集合,一旦到达视图,工作单元和NHibernate会话就会关闭。我必须在这种情况下使用急切加载,还是我误解了什么?
答案 0 :(得分:4)
恕我直言,懒加载是邪恶的!
存储库背后的想法是返回聚合。该聚合应包含 all 构成聚合的相关数据。它永远不会被加载。因此,总是应该热切地提取集合。
如果从等式中删除UoW / ORM,则延迟加载不是一个选项。
您应该尝试不来查询您的域名。如果您的情况是单个聚合包含您需要的所有数据并且数据已经公开,那么就可以了。
但是,我建议您使用读取模型。一个简单的查询图层。尝试一下,你可能会感到惊讶:)
答案 1 :(得分:1)
我意识到会话在方法完成之前结束(它包含在using
块中),这是在视图代码运行之前。所以,是的,您需要急切加载从NHibernate会话中返回的Enquiry
类型的集合属性中的项目。
更好的方法是设置工作单元模式,以便它包装管道中的整个请求。例如,如果您有Global.asax
个文件,则它有两个名为Application_BeginRequest
和Application_EndRequest
的方法。
Application_BeginRequest
方法将创建一个新的NHibernate会话,可以由您的控制器检索。
Application_EndRequest
方法只是刷新会话,保存对底层数据库的任何数据更改。
我引用了以下StackOverflow问题,将NHibernate会话与Global.asax
组件合并:NHibernate Session in global.asax Application_BeginRequest
答案 2 :(得分:0)
引入视图模型层而不是将原始实体传递给Controller将解决您的问题,因为映射到Person
视图模型(在using
子句内)将访问Person.Collection
并触发加载。
或者,正如@EbenRoux建议的那样,你可以拥有一个没有通过域名的整个阅读方。
答案 3 :(得分:0)
嗯,你想,不是吗?您处于一个用例中,您知道您希望Person.Collection可用,那么为什么不立即加载它。我必须在这种情况下使用急切加载,还是我误解了什么?
诀窍是不要使用你想要懒惰地加载集合时使用的相同存储库实现(或者根本不加载)。
Udi Dahan多次写到这个
Greg Young会提醒您,使用提取策略是一个实现细节,而不是合同的一部分