如果会话被处理掉,我必须使用Eager加载吗?

时间:2017-11-08 17:28:57

标签: c# nhibernate domain-driven-design

请参阅以下代码:

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会话就会关闭。我必须在这种情况下使用急切加载,还是我误解了什么?

4 个答案:

答案 0 :(得分:4)

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

存储库背后的想法是返回聚合。该聚合应包含 all 构成聚合的相关数据。它永远不会被加载。因此,总是应该热切地提取集合。

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

您应该尝试来查询您的域名。如果您的情况是单个聚合包含您需要的所有数据并且数据已经公开,那么就可以了。

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

答案 1 :(得分:1)

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

更好的方法是设置工作单元模式,以便它包装管道中的整个请求。例如,如果您有Global.asax个文件,则它有两个名为Application_BeginRequestApplication_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会提醒您,使用提取策略是一个实现细节,而不是合同的一部分