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

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_BeginRequestApplication_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 可用,那么为什么不立即加载它呢。

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

乌迪大汉写过很多次

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