为什么我的ILoadEventListener没有被调用?

本文关键字:调用 我的 ILoadEventListener 为什么 | 更新日期: 2023-09-27 18:07:23

我做了一个实现ILoadEventListener的类,并实现了一个OnLoad()方法(当然——否则它甚至不会编译)。在创建"new NHibernate.Cfg.Configuration()"之后,我按照文档所说的添加它:

configuration.EventListeners.LoadEventListeners = new ILoadEventListener[] {
    new MyListener(),
    new NHibernate.Event.Default.DefaultLoadEventListener()
};

然而,它似乎从来没有被调用-我已经添加了日志语句到我的OnLoad(),并在调试器中设置了一个断点-即使在使用我的应用程序的方式,清楚地从数据库中获取对象使用这个NHibernate会话工厂。

我错过了什么?

编辑:我在源代码(NHibernate事件文档是相当稀疏)戳了一下,发现对应于IInterceptor的事件实际上是PreLoad,而不是Load,所以我试着使用它,那一个确实着火了。所以我现在可以使用它,但我仍然不知道preload/load/postload是什么

为什么我的ILoadEventListener没有被调用?

这方面的文档几乎不存在,所以这可能会帮助一些人:

任何Load事件(Load/PreLoad/PostLoad)都不会在身份缓存中的实体上触发,即使您使用Get, Load或再次查询。

这种类型的如果你以正确的方式斜视它是有意义的,但是由于不确定性的行为,它会造成很大的挫折,因为大多数时候,你不会知道实体是否在缓存中。显然,这些事件是指水化一个实体的过程,而不是简单地请求它。

我还没有测试过这个理论,但如果从L2缓存命中的缓存也不触发Load事件,我也不会感到惊讶,因为这些实体也不会被激活。

在实践中,这意味着如果你想让一个特定的监听器在"每个"实体上运行,你需要考虑到它最初是一个由SaveUpdate等引入会话的瞬态实例的可能性。换句话说,如果你实现了IPostLoadEventListener,你可能也想实现IPostInsertEventListenerIPostUpdateEventListener

这实际上不会改变行为-侦听器仍然只会在实体与会话关联的第一个时间运行-但至少这保证了您可以从会话中检索的每个实体都被该侦听器截获。在我的情况下,我试图使用PostLoad向实体注入一些东西,所以这是一个可接受的解决方案。

如果你真的需要侦听器在每次检索实体时触发,你需要使用无状态会话(没有缓存)或在再次加载/查询之前驱逐实体。