c# - NHibernate - 查询在保存新实体后错过了查询缓存

标签 c# nhibernate fluent-nhibernate linq-to-nhibernate

我已经为 NHibernate(使用 NHibernate.LinqFluent NHibernate )设置了查询缓存。一切正常,直到我执行 session.Save(new Widget())(即 SQL INSERT)。在那之后,对该类型 Widget 的所有查询都会错过查询缓存。对其他实体类型的查询被缓存得很好。

using (ISession session = MySessionFactory.OpenSession())
{
    using (var transaction = session.BeginTransaction())
    {
        // this INSERT screws things up
        var widget = new Widget {Name = "Foo"};
        session.Save(widget);

        var query = (from w in session.Query<Widget>().Cacheable()
                     where w.Name == "Bar"
                     select w);

        var fetched1 = query.FirstOrDefault();
        var fetched2 = query.FirstOrDefault(); // miss?!

        transaction.Commit();
    }
}

如果我开始一个新的 Transaction,问题仍然存在。如果我开始一个新的 Session,问题就会消失。这似乎有点奇怪,因为我的理解是二级缓 stub 据 SessionFactory(而不是 Session)重置。

我认为这不重要,但我正在使用 HashtableCacheProvider,因为我现在只是在测试。

最佳答案

您描述的行为是正确的( more here )

The update timestamp cache is not updated until you commit the transaction! This is to ensure that you will not read "uncommitted values" from the cache.

每当我们在缓存中获得的 type 发生变化时——缓存的数据都是陈旧的……直到提交完整的事务。

假设您已缓存此过滤器的结果:

 var query = (from w in session.Query<Widget>().Cacheable()
  where w.Name == "B*" // all names starting with B
  select w);

稍后将添加新的 Widget:

var widget = new Widget {Name = "Brigitte"};
session.Save(widget);
// explicit Flush is not needed, 
// but then, until Commit(), query will never return Brigitte
session.Flush(); // to immediately execute INSERT

如果查询仍然被缓存,Brigitte 将永远不会出现......

而在事务中,使用 FirstOrDefault() 的查询会立即执行 - 写操作可以等待提交时刷新。

因为事务,所有包含的操作(插入、更新、选择)都不能从缓存中获利,因为只有作为批处理的事务才有意义。因此,在调用 commit 之前,无法使用缓存。

许多详细且非常有用的信息可以在这里找到:First and Second Level caching in NHibernate

The timestamp cache is updated whenever a table is written to, but in a tricky sort of way:

  • When we perform the actual writing, we write a value that is somewhere in the future to the cache. So all queries that hit the cache now will not find it, and then hit the DB to get the new data. Since we are in the middle of transaction, they would wait until we finish the transaction. If we are using low isolation level, and another thread / machine attempts to put the old results back in the cache, it wouldn't hold, because the update timestamp is into the future.
  • When we perform the commit on the transaction, we update the timestamp cache with the current value.

关于c# - NHibernate - 查询在保存新实体后错过了查询缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14299456/

相关文章:

asp.net - 蜘蛛抓取期间与事务相关的各种 NHibernate 错误

c# - 如何在 HQL 中使用 DATEPART 从 DATETIME 获取 YEAR

C# NHibernate 使用数据时出现 Spring LazyInitializationException

c# - Fluent nhibernate 映射多个表

c# - 将 Blazor RenderFragment 参数转发给子组件会引发异常

c# - 如何修复过时的 ILoggerFactory 方法?

c# - 命名 RESTful 路径

C# 声明同一个表的多个实例

c# - 无法创建 FluentNHibernate.Automapping.AutoMapping Namespace.Class[T] 的实例,因为 Type.ContainsGenericParameters 为真

c# - Fluent NHibernate 加入不使用主键