6

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と、問題はなくなります。SessionFactory私の理解では、2番目のレベルのキャッシュは(ではなく)ごとにリセットされるため、これはちょっと奇妙に思えSessionます。

これは重要ではないと思いますが、HashtableCacheProvider今テストしているだけなので、を使用しています。

4

1 に答える 1

6

あなたが説明した振る舞いは正しいです詳細はこちら

トランザクションをコミットするまで、更新タイムスタンプキャッシュは更新されません。これは、キャッシュから「コミットされていない値」を読み取らないようにするためです。

キャッシュにある変更があるときはいつでもtype-キャッシュされたデータは古くなっています...完全なトランザクションがコミットされるまで。

このフィルターの結果をキャッシュしたと想像してください。

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

そして後で新しいウィジェットを追加します:

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()を使用したクエリがすぐに実行されます。書き込み操作は、FlushonCommitを待機する可能性があります。

トランザクションのため、バッチとしてのトランザクションのみが意味をなすため、含まれているすべての操作(挿入、更新、選択)はキャッシュから利益を得ることができません。したがって、commitが呼び出されるまで、キャッシュは使用できません。

多くの詳細で非常に役立つ情報がここにあります:NHibernateの第1レベルと第2レベルのキャッシング

タイムスタンプキャッシュは、テーブルが書き込まれるたびに更新されますが、トリッキーな方法で更新されます。

  • 実際の書き込みを実行するときは、将来のどこかにある値をキャッシュに書き込みます。したがって、キャッシュにヒットしたすべてのクエリはキャッシュを検出せず、DBにヒットして新しいデータを取得します。私たちは取引の途中なので、彼らは私たちが取引を終えるまで待つでしょう。低い分離レベルを使用していて、別のスレッド/マシンが古い結果をキャッシュに戻そうとした場合、更新タイムスタンプが将来のものであるため、保持されません。
  • トランザクションでコミットを実行すると、タイムスタンプキャッシュが現在の値で更新されます。
于 2013-01-13T07:10:30.323 に答える