如果会话被释放,我必须使用预先加载



请参阅下面的代码:

public Enquiry GetByID(Guid personID)
{
    using (IUnitOfWork<ISession> unitOfWork = UnitOfWorkFactory.Create())
    {
        IRepository repository = RepostioryFactory.Create(unitOfWork);
        var Person = repository.GetById(personID);
        return Person;
    }
}

它包含在应用程序服务层中。 人员被传递回控制器并加载到视图中。 然后,视图出错,因为它无法加载 Person.Collection(列表)。

我相信这是因为集合是使用延迟加载加载的,一旦到达视图,工作单元和 NHibernate 会话就会关闭。 在这种情况下,我必须使用紧急加载还是误解了什么?

恕我直言,懒惰加载是邪恶的!

存储库背后的想法是返回聚合。 该汇总应包含构成聚合的所有相关数据。 它永远不会以位为单位加载。 因此,应该始终急切地获取聚合。

如果您从等式中删除 UoW/ORM,则延迟加载不是一种选择。

您应该尽量不要查询您的域。 如果单个聚合包含所需的所有数据并且该数据已公开,则可以。

但是,我建议您使用读取模型。 一个简单的查询图层。 试一试,你可能会感到惊讶:)

我意识到会话在方法完成之前结束(它包装在using块中),也就是在您的视图代码运行之前。所以是的,你确实需要预先加载集合属性中的项目,以你从 NHibernate 会话返回的Enquiry类型。

更好的方法是设置工作单元模式,使其在管道中环绕整个请求。例如,如果您有一个Global.asax文件,则它有两个方法,分别称为 Application_BeginRequestApplication_EndRequest

Application_BeginRequest 方法将创建一个新的 NHibernate 会话,控制器可以检索该会话。

Application_EndRequest 方法只需刷新会话,将任何数据更改保存到基础数据库。

我向您推荐以下 StackOverflow 问题,用于将 NHibernate 会话与 Global.asax 组件合并:global.asax Application_BeginRequest中的 NHibernate Session

引入视图模型层而不是将原始实体传递给控制器将解决您的问题,因为映射到Person视图模型(在 using 子句内)将访问Person.Collection并触发加载。

或者,你可以有一个不通过域的整个读取端,正如@EbenRoux所建议的那样。

在这种情况下,我必须使用紧急加载还是误解了什么?

好吧,你想,不是吗? 您处于一个用例中,您知道您希望 Person.Collection 可用,那么为什么不立即加载它。

诀窍是不要使用您希望延迟加载集合(或根本不加载)时使用的相同存储库实现。

乌迪·达汉(Udi Dahan)多次写过这个问题

  • http://udidahan.com/2007/03/06/better-domain-driven-design-implementation/
  • http://udidahan.com/2007/04/23/fetching-strategy-design/

Greg Young 会提醒您,使用获取策略是一个实现细节,而不是合同的一部分

  • http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/

最新更新