nHibernate 无法从存储库表中检索手动更改的数据?我也禁用了二级缓存,但看起来它(nhibernate)有时从缓存中检索,有时从存储库表中检索。
7 回答
nhibernate中有两种缓存:会话缓存和二级缓存。会话缓存始终缓存该会话看到的对象 - 这是 nhibernate 知道哪些对象已更改并需要持久化的方式。您禁用的二级缓存低于此值。您看到的缓存信息来自会话缓存。
如果您的应用程序需要查看由其他来源保留的更改(例如,手动数据库更改),答案可能是以更精细的粒度创建会话。虽然 SessionFactory 在应用程序的生命周期中存在,但应该更频繁地创建 Session 对象。例如,在 Web 应用程序中,每个请求都会生成自己的会话。
如果这不是一个选项, session.Clear() 将从会话中驱逐所有对象。
与 NHibernate 的良好关系始终取决于强大的 OO 承诺,并且在最常见的情况下取决于数据更改的排他性。如果你没有它,你会看到一些令人讨厌的问题,并且会放弃 NH 可以提供的大部分真正好的东西。
假设有一个名为“Foo”的类映射到具有“Id”和“SomeProperty”列的表“Foo”。如果所有行都手动将“SomeProperty”从“oldValue”更新为“newValue”,并且 NH 向 DB 发送一些查询,询问 SomeProperty =“newValue”的所有 Foos,则 DB 按预期返回所有 Foos。但是 Foo 实例 NH 提供的可能具有“oldValue”,因为具有返回 Id 的 Foo 已经附加到会话(换句话说,它位于一级缓存上)。
让 NHibernate 了解所有手动更新的唯一捷径是使用 StatelessSession,因此它不会缓存对象实例,并且始终提供数据库版本的数据。但是,如果您想在事务系统上应用它,这是不恰当使用 NH 的明显迹象,并且您将无法获得大部分好的 NH 功能。
我不知道它是否会解决您遇到的问题,但文档指出:
要从会话缓存中完全逐出所有对象,请调用 ISession.Clear()
对于二级缓存,在 ISessionFactory 上定义了一些方法,用于驱逐实例、整个类、集合实例或整个集合角色的缓存状态。
如果每次对可能带外更改的数据执行 SELECT 时都执行此操作,那么它应该执行您想要的操作。
这只是测试的一部分。
但将来我们可以手动编辑数据表。我还为该表设置了lazy 为false,并注释掉了hibernate 使用的所有二级缓存属性。但即便如此,它也会返回不同的值而不是新编辑的值。有时它给我旧的价值,有时给我新的价值,所以它不是恒定的。
抱歉太具体了
Nhibernate 正在毫无问题地检索数据。但是当我手动更改存储库表中的数据时。Icriterea(nhibernate) 有时会从缓存或表中获取。我正在使用 Icriteria 功能:
ICriteria 标准 = session.CreateCriteria(typeof(xyzclass)); criteria.Add(Expression.Eq("xyzclass", somestringto retreivedata)); 标准.SetCacheable(false); 返回条件.UniqueResult();
我从未实际使用过 NHibernate 的缓存功能,但我相信它的目的是完全消除访问数据库的需要,这意味着它不会接受手动更改,因为它不知道他们。
我会确切地质疑您在这里要实现的目标是什么,您只是通过手动编辑数据库进行一些测试,还是这将是实时应用程序中的常规活动?实际上,唯一应该修改数据库的是应用程序,通过您的 NHibernate 数据层进行修改,因此在此过程中更新和/或弄脏缓存。
我认为您必须对您的确切问题进行更多描述才能获得答案;我对 nhibernate 有一些最小的经验,但我不能真正去复制正在发生的事情并尝试在没有一些代码的情况下修复它。