在使用Rhino Commons UnitOfWork时(在ASP-MVC的UnitOfWorkApplication中),我喜欢使用Rhino Repository静态类来保存这样的实体: 通用标签

我发现我可以在调用之后立即使用以下方法将实体取出: 通用标签

这很好。但是,当我像这样在Rhino UnitOfWork上使用NHibernate Linq提供程序时: 通用标签

我得到一个空名单。看来我必须先致电UnitOfWork.Current.Flush(),然后才能将车开出。我不明白为什么,因为在幕后我假设两种检索方法都在查询相同的会话/工作单元。这是否意味着每次保存到数据库后都应调用UnitOfWork.Current.Flush()?NHibernate是否应该能够解决何时刷新自身的问题?还是我误会了什么?

有帮助吗?

解决方案

好吧,尽管对存储库的Get调用可以使用会话缓存,但也可以“查看”缓存中保存的汽车: 通用标签

linq查询不使用会话缓存: 通用标签

因此,最佳实践是对数据库的任何更改(保存,更新,删除,插入)都应跟随: 通用标签

或包装在: 通用标签

或使用[Transaction]装饰您的方法并使用ATM。这样可以确保后续的linq查询将查看最新数据。

其他提示

当调用Repository.Save时,您将通知存储库所举行的会话以跟踪该对象,并在下一次刷新时将更改同步到数据库。在刷新会话之前,不会对数据库进行任何更改。该对象确实成为了会话缓存的一部分,因此将由Get(1)返回。

运行查询以填充集合时,会话将查询数据库以获取结果,除非它已经缓存了这些结果。 由于尚未更新数据库,因此添加到会话中的Car不会成为结果集的一部分。(<-可能不正确)如果我正确阅读了文档,则都查询结果和Save()版本的实体应添加到会话(第一级)缓存中。这并不一定意味着在添加数据库结果后,querystatement.List()会查询缓存...我很难理解到底发生了什么。

顺便说一句,我相信您可以将会话设置为自动刷新,但是我必须检查文档。

更新:

我想我可能会发现这里发生了什么。默认的会话FlushModeAuto,但是Rhino的UnitOfWork.Start()创建的会话中将FlushMode设置为Commit,这意味着除非您明确调用Flush()或提交交易,否则会话不会自动刷新。使用FlushModeAuto时,NHibernate会(有时?)在查询之前刷新会话,以防止返回陈旧的数据。如果我是对的,那么您的数据库事务如下所示: 通用标签

当从我阅读的文档/博客中看它自动刷新时,似乎有些含糊……最常见的答案是,它与FlushMode = Auto一起“有时”刷新,尽管可以保证Session.Find永远不会返回过时的数据。由于NHibernate Linq实际上只是创建一个Criteria查询,因此它可能不会触发自动刷新(也许现在已经解决了……很难知道)。

在我看来,在您的情况下,您想在保存后刷新,因为您立即想检索保存的结果。在仅更新实体的较小的工作单元中,单个Commit()会很好。也许UnitOfWork.CurrentSession.FlushMode = FlushMode.Auto;可以解决问题,但UOW工厂明确将模式设置为Commit的事实似乎鼓励您真正考虑自己的UOW边界。

感谢Stuart Childs,我怀疑他是对的,这个问题可能与NHibernate Linq提供程序有关。我不确定它在幕后做什么,但是它可能使用不同的会话,如果这样做,那么在Linq查询“看到”它之前我必须刷新存储库保存是有意义的。是时候仔细阅读源代码了,但是有人告诉我,它会让我理解我的头脑!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top