0

NHibernate で条件クエリを実行するとき、キャッシュから古い結果ではなく、新しい結果を取得したいと考えています。

プロセスは基本的に次のとおりです。

  1. 永続オブジェクトを NHibernate アプリケーションに照会します。
  2. データベース エントリを外部で変更します (別のプログラム、SSMS / MSSQL での手動編集など)。
  3. 持続性オブジェクトを照会します (同じ照​​会コードを使用)。以前にロードされたオブジェクトはデータベースからリフレッシュされます。

コードは次のとおりです (オブジェクト名が少し変更されています)。

public IOrder GetOrderByOrderId(int orderId)
{    
...
IList result;
var query = 
    session.CreateCriteria(typeof(Order))
        .SetFetchMode("Products", FetchMode.Eager)
        .SetFetchMode("Customer", FetchMode.Eager)
        .SetFetchMode("OrderItems", FetchMode.Eager)
        .Add(Restrictions.Eq("OrderId", orderId));
query.SetCacheMode(CacheMode.Ignore);
query.SetCacheable(false);

result = query.List();
...
}

SetCacheMode と SetCacheable は、キャッシュを無効にするために私が追加しました。また、NHibernate ファクトリーは構成パラメーター UseQueryCache=false でセットアップされます。

Cfg.SetProperty(NHibernate.Cfg.Environment.UseQueryCache, "false");

Put/Refresh キャッシュ モードを含め、クエリまたはセッションに対して何をしても、NHibernate はクエリが 2 回目に呼び出されたときに、外部でコミットされた変更なしで古いオブジェクトを返し続けます。情報: この場合の古い値は、バージョン列の値です (保存する前に古いオブジェクトの状態を検出できるかどうかをテストするため)。しかし、複数の理由から、新しいクエリ結果が必要です!

Hibernate は SQL クエリを生成しますが、返される値には使用されません。

セッションを開いたままにしておくことは、ダーティ カラムに対してのみ動的な更新を行うために必要です (解決のためのステートレス セッションもありません!)。特にクエリが下位レベルにあり、以前にロードされたオブジェクトを覚えていないため、Clear()、Evict() などをコードのどこにでも追加したくありません。悲観的ロックはパフォーマンスを低下させます (マルチユーザー環境!)

不要なキャッシュ機能を使用せずに、構成によってNHibernateにクエリをDBに直接送信させ、新しい結果を取得させる方法はありますか?

4

2 に答える 2

1

まず第一に、これは第2レベルのキャッシング(これが何であり、制御するか)とは何の関係もありません。たとえそうだったとしても、それらは返されたエンティティのキ​​ャッシュではなく、クエリのキャッシュを制御します。SetCacheModeSetCacheable

オブジェクトが現在のセッションにすでにロードされている場合(キャッシュではなくIDマップですが、一部の人は「第1レベルのキャッシュ」とも呼ばれます)、任意のメソッドを使用してDBからオブジェクトを再度クエリしても、その値が上書きされることはありません。

これは仕様によるものであり、このように動作するのには十分な理由があります。

クエリを使用して複数のレコードで変更される可能性のある値を更新する必要がある場合は、以前Evictそれらを更新する必要があります。

または、ステートレスセッションについて読むこともできます。

于 2012-07-05T22:57:32.687 に答える
0

このコードはトランザクションで実行されていますか?または、その外部プロセスはトランザクションで実行されていますか?これら2つのうちの1つがまだトランザクションにある場合、更新は表示されません。

そうでない場合は、NHibernateが作成しているログメッセージで問題を見つけることができる場合があります。これらは非常に有益であり、常にそれが何をしているのかを正確に教えてくれます。

ダーティカラムのみで動的更新を行うには、セッションを開いたままにしておく必要があります

これは問題であるか、将来問題になるでしょう。NHibernateはあなたの人生をより良くするためにできる限りのことをしていますが、あなたはNHibernateがその仕事を適切に行うのを防ぐために可能な限りのことをしようとしています。

NHibernateでダーティ列のみを更新する場合は、クラスマッピングファイルのdynamic-update-attributeを確認できます。

于 2012-07-09T12:08:52.913 に答える