1

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

备注

  • 堆栈跟踪示例:http: //textsnip.com/613608
  • 我们不会在项目中的任何地方处理(或将会话包装在使用中)。我们让 ObjectFactory 处理它。
  • 在我们的 TeamCity 测试环境中运行回归测试(带有 WatiN 的 SpecFlow)时发生。我们没有人能够在我们的开发机器上重现该问题。
  • 这也不会始终如一地发生。虽然失败的测试通常是相同的测试,但它们不会一直失败。访问会命中某些相同视图的页面的其他测试不会失败。
  • 在确实失败的测试中,它们似乎更倾向于延迟加载集合初始化而不是非集合,但两者都发生了。
  • 虽然我知道尽可能提前加载实体会更好,但由于我们的许多表模型相互依赖,目前还不是那么可行。

我们在这里缺少什么?

4

2 回答 2

1

您的实体加载模式在视图中称为开放会话,它被视为反模式。更多关于这种模式的缺点herehere

推荐的方法是使用一些带有预取数据的视图模型。但是如果你做不到,你可以使用 linq 预取模型数据来休眠扩展扩展。有一个开源库ITDT.Sentia,它提供了类型化的扩展扩展,或者您可以在谷歌中搜索“nhibernate expand”。对于更底层的东西,你可以看看 nhibernate fetching strategy 。

例如使用 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();

至于开发环境中的不同行为,我只能猜测它以某种方式使用了其他一些配置文件,也许有不同的调试/发布 web.configs?

于 2012-04-18T18:45:55.540 回答
0

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

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

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

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

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

于 2012-04-18T16:14:42.437 回答