2

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

Repository<Car>.Save(new Car(Id = 1));

我发现我可以在调用之后立即使用:

Car car = Repository<Car>.Get(1);

这工作正常。但是,当我在 Rhino UnitOfWork 上使用 NHibernate Linq 提供程序时,如下所示:

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()
               select rep).ToList();

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

4

3 回答 3

2

好吧,虽然对 Repository 的 Get 调用可以使用会话缓存,但似乎可以“看到”缓存中保存的汽车:

Car car = Repository<Car>.Get(1); // This works because it uses the same session

linq 查询不使用会话缓存:

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()               
select rep).ToList(); // Does not work, even if it is in the same code block and even though it uses the same session

因此最佳实践是任何数据库更改(保存、更新、删除、插入)都应遵循:

UnitOfWork.Session.Flush(), 

或包裹在:

With.Transaction(delegate{
   // code here
})

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

于 2009-03-25T17:00:17.707 回答
1

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

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

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

更新:

我想我可能会看到这里发生了什么。默认会话FlushModeAuto,但 RhinoUnitOfWork.Start()会创建一个FlushMode设置为Commit的会话,这意味着会话不会自动刷新,除非您明确调用Flush()或提交事务。使用FlushModeof Auto,NHibernate 将(有时?)在查询之前刷新会话,以防止返回过时的数据。如果我是对的,您的数据库事务看起来像:

SELECT * FROM Car

INSERT INTO Car (...) VALUES (...)

从我读过的文档/博客来看,当它自动刷新时似乎有点模棱两可......最常见的答案是它FlushMode = Auto“有时”会刷新,尽管它保证Session.Find永远不会返回陈旧的数据。由于 NHibernate Linq 实际上只是创建了一个 Criteria 查询,它可能不会触发自动刷新(也许现在已经修复了......很难知道)。

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

于 2009-03-19T15:33:08.900 回答
0

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

于 2009-03-20T11:48:08.917 回答