2

Rhino Commons UnitOfWork (ASP-MVC の UnitOfWorkApplication 内) を使用する場合、Rhino リポジトリの静的クラスを使用して、次のようにエンティティを保存します。

Repository<Car>.Save(new Car(Id = 1));

次を使用して、その呼び出しの直後にエンティティを取得できることがわかりました。

Car car = Repository<Car>.Get(1);

これはうまくいきます。ただし、Rhino UnitOfWork で NHibernate Linq プロバイダーを次のように使用すると、次のようになります。

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()
               select rep).ToList();

空のリストを取得します。このように車を出す前に、 UnitOfWork.Current.Flush() を呼び出す必要があるようです。舞台裏では、両方の取得方法が同じセッション/作業単位を照会していると想定しているため、理由がわかりません。これは、データベースに保存するたびに UnitOfWork.Current.Flush() を呼び出す必要があるということですか? NHibernate は自分自身をいつフラッシュするかを判断できるはずではありませんか? それとも私は何かを誤解していますか?

4

3 に答える 3

2

レポジトリへの Get 呼び出しはセッション キャッシュを使用できますが、キャッシュに保存された車を「見る」ことができるようです。

Car car = Repository<Car>.Get(1); // This works because it uses the same session

linq クエリはセッション キャッシュを使用しません。

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()               
select rep).ToList(); // Does not work, even if it is in the same code block and even though it uses the same session

そのため、ベスト プラクティスは、データベースの変更 (保存、更新、削除、挿入) の後に次の手順を実行することです。

UnitOfWork.Session.Flush(), 

またはラップ:

With.Transaction(delegate{
   // code here
})

または [Transaction] でメソッドを装飾し、ATM を使用します。これにより、後続の linq クエリが最新のデータを参照するようになります。

于 2009-03-25T17:00:17.707 に答える
1

Repository.Save を呼び出すと、リポジトリが保持するセッションに通知して、そのオブジェクトを追跡し、次のフラッシュでデータベースへの変更を同期します。セッションをフラッシュするまで、データベースは変更されません。ただし、オブジェクトはセッション キャッシュの一部になるため、Get(1) によって返されます。

クエリを実行してコレクションにデータを入力すると、セッションはデータベースにクエリを実行して結果を取得します (結果がキャッシュされていない場合)。データベースをまだ更新していないため、セッションに追加した車は結果セットに含まれません。(<-- 間違っている可能性があります) ドキュメントを正しく読んでいれば、クエリ結果と Save() されたエンティティの両方をセッション (第 1 レベル) キャッシュに追加する必要があります。これは、DB の結果を追加した後にキャッシュをクエリすることを必ずしも意味するわけではありませんquerystatement.List()...何が起こっているのかを正確に把握するのに苦労しています。

余談ですが、セッションを自動フラッシュに設定できると思いますが、ドキュメントを確認する必要があります。

アップデート:

ここで何が起こっているのかわかるかもしれないと思います。デフォルトのセッションFlushModeは ですAutoが、Rhinoは に設定されUnitOfWork.Start()たセッションを作成します。これは、トランザクションを明示的に呼び出すかコミットしない限り、セッションが自動フラッシュされないことを意味します。of を使用すると、NHibernate は (場合によっては?) 古いデータが返されるのを防ぐためにクエリを実行する前にセッションをフラッシュします。私が正しければ、DB トランザクションは次のようになります。FlushModeCommitFlush()FlushModeAuto

SELECT * FROM Car

INSERT INTO Car (...) VALUES (...)

自動フラッシュは、私が読んだドキュメント/ブログから少しあいまいに思えます...最も一般的な答えは、古いデータを決して返さないことをFlushMode = Auto保証しますが、「時々」フラッシュするということです。Session.FindNHibernate Linq は実際には Criteria クエリを作成するだけなので、自動フラッシュをトリガーしない可能性があります (おそらくこれは現在修正されています... 知るのは難しいです)。

したがって、あなたの場合、保存の結果をすぐに取得したいので、保存後にフラッシュしたいようです。エンティティのみを更新する小規模な作業単位では、単一の Commit() で十分です。うまくいくかもしれUnitOfWork.CurrentSession.FlushMode = FlushMode.Auto;ませんが、UOW Factory が明示的にモードを Commit に設定しているという事実は、UOW の境界について真剣に考えることを奨励しているようです。

于 2009-03-19T15:33:08.900 に答える
0

Stuart Childsのおかげで、問題はNHibernateLinqプロバイダーにあるのではないかと彼は正しいと思います。舞台裏で何が行われるかはわかりませんが、別のセッションを使用する可能性があります。その場合、Linqクエリが「表示」する前にリポジトリの保存をフラッシュする必要があります。ソースコードを調べてみましょう。しかし、それを理解しようとすると頭が溶けると言われています。

于 2009-03-20T11:48:08.917 に答える