我有以下问题。 我已经在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));
}
我尝试了两种不同的&#34; GetByID&#34;的实现,其中一种使用 会议&#34; get&#34;方法,另一个使用查询方法与fetch语句类似 到PreLoadStudents学生方法。
在&#34; get&#34;方法,发生缓存命中和测试通过。 在&#34;查询&#34;的情况下,没有发生缓存命中或未命中,而是执行了2个查询。
这是我用于&#34; GetByID&#34;的代码。方法使用&#34; Get&#34;方法
var student = session.Get<Student>(studentId);
我不喜欢这种方法,因为我无法获取延迟加载的子集合
这是我用于&#34; GetByID&#34;的代码。使用&#34; QueryOver&#34;的方法方法
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();
关于&#34; get&#34;方法生成了一个命中而查询方法没有?
答案 0 :(得分:2)
在阅读并做了一些实验测试后,这是我的问题出现的解决方案。
我最初的问题 - 关于为什么“get”方法在查询方法时没有产生命中的任何想法?是一个误解的问题,原因如下:
因此
经验教训
答案 1 :(得分:1)
二级缓存仅在您有交易时才有效,这对于查询来说也是一种很好的做法。
using (ISession session = NHibernateHelper.OpenSession())
using (ITransaction tx = session.BeginTransaction())
{
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>();
tx.Commit();
}