我什么时候需要冲洗Rhino Commons UnitOfWork?
-
20-08-2019 - |
题
在使用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()
会查询缓存...我很难理解到底发生了什么。
顺便说一句,我相信您可以将会话设置为自动刷新,但是我必须检查文档。
更新:
我想我可能会发现这里发生了什么。默认的会话FlushMode
是Auto
,但是Rhino的UnitOfWork.Start()
创建的会话中将FlushMode
设置为Commit
,这意味着除非您明确调用Flush()
或提交交易,否则会话不会自动刷新。使用FlushMode
的Auto
时,NHibernate会(有时?)在查询之前刷新会话,以防止返回陈旧的数据。如果我是对的,那么您的数据库事务如下所示:
通用标签
当从我阅读的文档/博客中看它自动刷新时,似乎有些含糊……最常见的答案是,它与FlushMode = Auto
一起“有时”刷新,尽管可以保证Session.Find
永远不会返回过时的数据。由于NHibernate Linq实际上只是创建一个Criteria查询,因此它可能不会触发自动刷新(也许现在已经解决了……很难知道)。
在我看来,在您的情况下,您想在保存后刷新,因为您立即想检索保存的结果。在仅更新实体的较小的工作单元中,单个Commit()会很好。也许UnitOfWork.CurrentSession.FlushMode = FlushMode.Auto;
可以解决问题,但UOW工厂明确将模式设置为Commit的事实似乎鼓励您真正考虑自己的UOW边界。
感谢Stuart Childs,我怀疑他是对的,这个问题可能与NHibernate Linq提供程序有关。我不确定它在幕后做什么,但是它可能使用不同的会话,如果这样做,那么在Linq查询“看到”它之前我必须刷新存储库保存是有意义的。是时候仔细阅读源代码了,但是有人告诉我,它会让我理解我的头脑!