【发布时间】:2010-01-13 18:03:43
【问题描述】:
我开始将基于 Sharepoint 的 ASP.NET 项目中的一些预先存在的 nHibernate 代码从急切加载和每个数据库命中的新会话切换到延迟加载和 HTTP 请求期间的会话,并开始运行一个问题。
当我们在这个系统中创建一个项目时,有一些由下拉列表填充的多对一关系。这为我们提供了 ID,这足以保存到数据库中。
为了执行一些保存后的任务,例如电子邮件通知,然后我们将相同的项目加载回来,这之前会填充整个对象树。
但是,自从更改为延迟加载和会话与整个请求的生命周期以来,我们一直在从 Item 下面的属性中获取 NullReferenceExceptions,这些属性神秘地为 null。
我们通过 nHibernate 将项目加载到 changedItem 中。失败的调用是:
changedItem.PaperMedia.FormsAnalyst.User.Contact.Name
PaperMedia 已完全填充,但 FormsAnalyst 上的所有内容都为空,除了 ID。
这与我们保存时的状态相同,因此导致此问题的一个可能原因是项目被缓存并简单地检索,因此 nHibernate 不知道数据库中的实际值。但是,我正在提交事务,并在保存和后续加载之间在会话上显式调用 Flush(),所以如果是这种情况,那么 Commit() 和 Flush() 都不会对缓存产生任何影响。
我已将相关 hbm.xml 文件中的这些属性更改为lazy="false",并为所有这些属性设置了 SetFetchMode FetchMode.Eager,但没有任何效果。
我也在考虑 max_fetch_depth 作为问题。如果我在会话上调用 Refresh(changedItem),它没有效果。但是,如果我调用 Refresh(changedItem.PaperMedia),它将一直填充到 Name。这似乎将 max_fetch_depth 视为问题,但我仍然尝试增加它,将其设置为 hibernate.cfg.xml 中的 6 以及配置实例上的 SetProperty("max_fetch_depth", "6")在创建会话工厂时,这些也没有效果。
我不知道还能尝试什么。
有人见过这样的事情吗?我是 nHibernate 的新手,所以它可能很简单......
编辑:
看起来缓存确实是问题所在。在会话实例上调用 Clear() 可修复此行为。
所以现在的问题变成了,为什么 Flush() 不会更新缓存的项目?这正是我认为它的目的。
【问题讨论】:
-
发生这种情况时,FormsAnalyst 是生成的代理类吗?我没有使用 max_fetch_depth 但我认为它只适用于急切加载。
-
是的,您可能是对的,但不,此时它是一个实际的 UserAnalyst 对象,因为我急切地加载它以试图解决问题。在我开始弄乱我的 hbm.xml 文件和我的获取模式等之前,我相信它是一个代理对象,但我还没有找到一个除了 NullReferenceException 之外的组合。
标签: nhibernate session lazy-loading nullreferenceexception flush