如果会话被处理,我必须使用预加载吗?
Must I use Eager loading if the session is disposed of?
请看下面的代码:
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 会话就会关闭。在这种情况下我必须使用预加载还是我误解了什么?
我意识到会话在方法完成之前结束(它包装在 using
块中),这是在您的视图代码运行之前。所以是的,您确实需要在从 NHibernate 会话返回的 Enquiry
类型中预先加载集合 属性 中的项目。
更好的方法是设置工作单元模式,使其环绕管道中的整个请求。例如,如果您有一个 Global.asax
文件,它有两个方法,称为 Application_BeginRequest
和 Application_EndRequest
.
Application_BeginRequest
方法将创建一个新的 NHibernate 会话,您的控制器可以检索该会话。
Application_EndRequest
方法只会刷新您的会话,将任何数据更改保存到基础数据库。
我建议您参考以下关于将 NHibernate 会话与 Global.asax
组件合并的 Whosebug 问题:NHibernate Session in global.asax Application_BeginRequest
恕我直言,延迟加载是邪恶的!
存储库背后的想法是 return 聚合。该聚合应包含 all 构成聚合的相关数据。它从不加载位。因此,应该始终急切地获取聚合。
如果您从等式中删除 UoW/ORM,则延迟加载不是一个选项。
您应该尝试而不是来查询您的域。如果您遇到这样一种情况,即单个聚合包含您需要的所有数据并且该数据已公开,那么就可以了。
但是,我建议您使用读取模型。一个简单的查询层。试一试,您可能会感到惊讶 :)
引入视图模型层而不是将原始实体传递给控制器将解决您的问题,因为映射到 Person
视图模型(在 using
子句内)将访问 Person.Collection
并触发加载。
或者,如@EbenRoux 所建议的那样,您可以拥有不通过域的整个读取端。
Must I use eager loading in this situation or am I misunderstanding something?
好吧,你想要,不是吗?您所处的用例中您知道希望 Person.Collection 可用,那么为什么不立即加载它呢。
诀窍是不要使用您希望延迟加载(或根本不加载)集合时使用的相同存储库实现。
乌迪大汉写过很多次
- http://udidahan.com/2007/03/06/better-domain-driven-design-implementation/
- http://udidahan.com/2007/04/23/fetching-strategy-design/
Greg Young 提醒您,使用抓取策略是一个实现细节,而不是合同的一部分
请看下面的代码:
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 会话就会关闭。在这种情况下我必须使用预加载还是我误解了什么?
我意识到会话在方法完成之前结束(它包装在 using
块中),这是在您的视图代码运行之前。所以是的,您确实需要在从 NHibernate 会话返回的 Enquiry
类型中预先加载集合 属性 中的项目。
更好的方法是设置工作单元模式,使其环绕管道中的整个请求。例如,如果您有一个 Global.asax
文件,它有两个方法,称为 Application_BeginRequest
和 Application_EndRequest
.
Application_BeginRequest
方法将创建一个新的 NHibernate 会话,您的控制器可以检索该会话。
Application_EndRequest
方法只会刷新您的会话,将任何数据更改保存到基础数据库。
我建议您参考以下关于将 NHibernate 会话与 Global.asax
组件合并的 Whosebug 问题:NHibernate Session in global.asax Application_BeginRequest
恕我直言,延迟加载是邪恶的!
存储库背后的想法是 return 聚合。该聚合应包含 all 构成聚合的相关数据。它从不加载位。因此,应该始终急切地获取聚合。
如果您从等式中删除 UoW/ORM,则延迟加载不是一个选项。
您应该尝试而不是来查询您的域。如果您遇到这样一种情况,即单个聚合包含您需要的所有数据并且该数据已公开,那么就可以了。
但是,我建议您使用读取模型。一个简单的查询层。试一试,您可能会感到惊讶 :)
引入视图模型层而不是将原始实体传递给控制器将解决您的问题,因为映射到 Person
视图模型(在 using
子句内)将访问 Person.Collection
并触发加载。
或者,如@EbenRoux 所建议的那样,您可以拥有不通过域的整个读取端。
Must I use eager loading in this situation or am I misunderstanding something?
好吧,你想要,不是吗?您所处的用例中您知道希望 Person.Collection 可用,那么为什么不立即加载它呢。
诀窍是不要使用您希望延迟加载(或根本不加载)集合时使用的相同存储库实现。
乌迪大汉写过很多次
- http://udidahan.com/2007/03/06/better-domain-driven-design-implementation/
- http://udidahan.com/2007/04/23/fetching-strategy-design/
Greg Young 提醒您,使用抓取策略是一个实现细节,而不是合同的一部分