【发布时间】:2025-12-08 23:20:10
【问题描述】:
我有以下问题。 我在 nHibernate(使用 Postgres)上启用了二级缓存系统,如下所示 配置
cfg.SessionFactory().Caching.Through<RtMemoryCacheProvider>().WithDefaultExpiration(28800);
我只启用实体缓存,因为此时我不需要查询缓存。
在我的实体中,这是我的设置(它们有些是读写的,有些是只读的,此时可以将更多设置为只读)
<id name="StudentID" access="property" column="`StudentID`">
<generator class="native" />
</id>
<property name="Name" column="`Name`" >
<property name="Address" column="`Address`" />
<property name="IsActive" column="`IsActive`" />
<property name="DateCreated" column="`DateCreated`" />
<property name="DateLastUpdated" column="`DateLastUpdated`" />
<property name="LastUpdatedBy" column="`LastUpdatedBy`" />
<set name="Projects" inverse="true" mutable="false">
<cache usage="read-only"/>
<key column="`StudentID`" />
<one-to-many class="Project" />
</set>
<set name="Classes" inverse="true" mutable="false">
<cache usage="nonstrict-read-write"/>
<key column="`StudentID`" />
<one-to-many class="Class" />
</set>
<set name="Books" inverse="true" mutable="false">
<cache usage="nonstrict-read-write"/>
<key column="`StudentID`" />
<one-to-many class="Book" />
</set>
</class>
在对我的解决方案进行单元测试时 - 我首先预先获取学生列表,然后尝试生成 缓存命中
public bool PreLoadStudents()
{
using (ISession session = NHibernateHelper.OpenSession())
{
IList<Student> results = session.QueryOver<Student>()
.Fetch(d => d.Projects).Eager
.Fetch(d => d.Classes).Eager
.Fetch(d => d.Books).Eager
.TransformUsing(Transformers.DistinctRootEntity)
.List<Student>();
}
}
[Test]
public void GetByIdTest()
{
bool bLoaded = testBLL.PreLoadStudents();
var student1 = testBLL.GetByID("123");
var student2 = testBLL.GetByID("123");
long cacheHit = testBLL.GetSessionFactory().Statistics.SecondLevelCacheHitCount;
Assert.That(cacheHit,Is.EqualTo(2));
}
我尝试了两种不同的“GetByID”实现,其中一种使用 约定“get”方法,另一种使用与 fetch 语句类似的查询方法 到 PreLoadStudents 学生方法。
在“get”方法的情况下,缓存命中发生并且测试通过。 在“查询结束”的情况下,不会发生缓存命中或未命中,而是执行了 2 个查询。
这是我使用“Get”方法用于“GetByID”方法的代码
var student = session.Get<Student>(studentId);
我不喜欢这种方法,因为我无法获取延迟加载的子集合
这是我使用“QueryOver”方法用于“GetByID”方法的代码
var student = session.QueryOver<Student>()
.Where(d => d.studentId == currentStudentId)
.Fetch(d => d.Projects).Eager
.Fetch(d => d.Classes).Eager
.Fetch(d => d.Books).Eager
.SingleOrDefault();
有什么想法为什么“get”方法会产生命中而query over 方法没有?
【问题讨论】:
-
您是否启用了查询缓存?二级缓存和查询缓存是有区别的。此外,您必须在 QueryOver 查询中使用
.Cacheable()。 -
是的 - 经过几次尝试,我确实启用了查询缓存和实体缓存。可以说我现在了解查询与获取。另外,我了解到查询缓存将使用二级缓存中的数据填充结果
标签: c# postgresql caching nhibernate