MVC3视图中的Lazy Loaded NHibernate实体

时间:2012-04-17 21:19:46

标签: asp.net-mvc-3 nhibernate

我的工作有问题。当我们尝试从MVC3视图中访问NHibernate实体上的延迟加载属性时,将抛出“No Session”LazyInitializationException。这只是在上周开始出现在我们身上,但我们无法缩小问题的范围。看起来并不是一个简单的解决方案。

备注

  • 堆栈跟踪示例:http://textsnip.com/613608
  • 我们不会在项目的任何位置处置(或将Session包装在使用中)。我们让ObjectFactory处理它。
  • 运行回归测试(带有WatiN的SpecFlow)时,我们的TeamCity测试环境中只发生 。我们都不能在我们的开发机器上重现这个问题。
  • 这也不会持续发生。虽然失败的测试通常是相同的测试,但它们并不会一直失败。访问能够访问某些相同视图的页面的其他测试不会失败。
  • 在失败的测试中,他们似乎更倾向于延迟加载集合初始化而不是非收集,但两者都发生了。
  • 虽然我知道在任何可能的情况下都渴望加载实体会更好,但是由于我们很多桌面模型的相互依赖性,目前并不是那么可行。

我们在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

您的实体加载模式在视图中称为开放会话,它被视为反模式。有关此模式的更多信息herehere

推荐的方法是使用一些具有预取数据的视图模型。但是如果你不能这样做,你可以使用linq预取模型数据到nhibernate扩展扩展。有一个开源库ITDT.Sentia,它提供了类型化的扩展扩展,或者你可以在google中搜索“nhibernate expand”。有关更低级别的内容,您可以查看nhibernate fetching strategies

例如使用ITDT.Sentia库并具有以下模型:

public class User : BaseEntity
{
    public virtual string Email { get; set; }
    public virtual Company Company { get; set; }
}

public class Company : BaseEntity
{
    public virtual string Name { get; set; }
}

假设在获取用户后延迟加载公司实体,您可以执行以下操作:

IList<User> users = userRepository
  .GetAll()
  .Where(u => /*some constraints*/)
 // here you are telling nhibernate to make a join and eger load what you need
  .Expand(u  => u.Company) 
  .ToList();

至于dev-environment中的不同行为,我只能猜测它是在使用其他一些配置文件,也许有不同的调试/发布web.configs?

答案 1 :(得分:0)

您是否直接绑定到视图中的对象模型?这听起来像你的问题,因为你查看直接绑定到域对象。由于域对象具有惰性集合,因此它尝试按需加载集合元素,这需要Nhibernate会话。

您应该在控制器方法中构建完整的视图模型。

我的建议是为您拥有的每个视图创建一个视图模型。然后,当您查询NHibernate时,直接投影到模型中或使用Automapper将对象模型转换为视图模型。直接投影的好处是通过nhibernate进行查询会更有效率,因为它只会选择你需要的列。

另见本文。 http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

它是视图模型的一组创建最佳实践。