Asp.net mvc Nhibernate/MVC:在视图中处理延迟加载的集合

Asp.net mvc Nhibernate/MVC:在视图中处理延迟加载的集合,asp.net-mvc,nhibernate,asp.net-mvc-2,Asp.net Mvc,Nhibernate,Asp.net Mvc 2,我目前正在使用一种基于属性的方法来管理nhibernate会话,这意味着会话在Action方法期间是打开的,但一旦将控件传递给视图,会话就会关闭 这对我来说似乎是一个很好的实践,但是我遇到了延迟加载集合的问题。(这一点很复杂,因为有些集合似乎是延迟加载的,即使它们在fluent映射中没有设置.LazyLoad()) 在我看来,我的选择是: 更改我的会话管理策略,并在视图中保持会话打开 更好地利用ViewModels(我目前没有在任何地方使用它们) 急切加载导致问题的所有集合(可能已分页)(无法承

我目前正在使用一种基于属性的方法来管理nhibernate会话,这意味着会话在Action方法期间是打开的,但一旦将控件传递给视图,会话就会关闭

这对我来说似乎是一个很好的实践,但是我遇到了延迟加载集合的问题。(这一点很复杂,因为有些集合似乎是延迟加载的,即使它们在fluent映射中没有设置.LazyLoad())

在我看来,我的选择是:

  • 更改我的会话管理策略,并在视图中保持会话打开
  • 更好地利用ViewModels(我目前没有在任何地方使用它们)
  • 急切加载导致问题的所有集合(可能已分页)(无法承受流利问题)
  • 1似乎有点错误,但可能是“最简单”的解决方案。2可能是正确的方法,但在某些情况下,ViewModels似乎有点多余,我不愿意引入更多的类来处理这个问题。3看起来有点脏


    您怎么看?

    将您当前的用法视为进行隐式数据库操作。该对象被发送到视图,但该对象包含代理,当触摸该代理时,将尝试返回数据,这需要数据库操作

    现在,

  • 延长ISession的生命周期(包括视图),这并没有错,只要您没有执行显式数据库调用
  • 我不知道那件事
  • 不管会话EOL如何,这实际上是正确的方法:您应该尝试对每个请求执行尽可能少的查询,而nhibernate通过懒散的加载、未来、多HQL/标准等为您提供了这种能力

  • 注意:尽管您可能已将集合映射为非延迟加载,但如何查询和获取所需的结果集也很重要。例如,如果您正在使用HQL,那么就使用一个获取连接

    处理这个问题的最佳方法(无论如何,我认为)是在您的UI和存储库之间引入一个服务层;它应该负责加载视图所需的所有内容,并向视图传递一个展开(并完全填充)的dto

    通常,我会更进一步,将从服务层返回的DTO映射到视图模型,视图模型通常需要包含非常特定于视图的数据,并且不适合包含在来自服务层的DTO中。记住,在这种情况下,朋友是你的朋友


    使用视图中的开放会话模式仍然是完全可以接受的,只是不要让视图在实体模型上调用延迟加载-这几乎总是一个可怕的想法。

    我认为第一种方法没有任何错误,而且它将是最容易实现的


    每个请求的会话是NHibernate众所周知的会话管理模式。

    感谢您的回答-不急于加载的查询基于ICriteria,而不是HQL。谢谢DanP。我试过用Automapper做实验。这看起来很有希望,但是,当我将实体上的集合映射到ViewModel上的集合时,这似乎仍然会触发延迟加载(即使视图只能访问视图模型)。我只能假设在这种情况下传递了对代理的引用。关于如何强制Automapper从集合(而不是代理)跨真实对象进行复制,您有什么建议吗?@UpTheCreek:simple,也可以使用DTO集合。不要从服务层发送NHibernate中映射的任何内容(例如,您的实际域类)。这听起来让人望而生畏,但automapper确实让这变得很简单…+1不是视图中打开会话的全部要点,这样您就可以从视图中进行延迟加载了吗?这就是为什么我从不为它烦恼。@dotjoe:部分,但还有其他好处。。。例如:如何跨多个服务层调用使用一级缓存?插入/更新/删除的批处理?有充分的理由在整个页面生命周期中保持会话打开。是的,但服务层调用是在controller中完成的。或者,你是说使用渲染,让多个动作方法使用同一个会话?