とき私は、RhinoのコモンズのUnitOfWorkをフラッシュする必要がありますか?
-
20-08-2019 - |
質問
(ASP-MVCのためUnitOfWorkApplicationに)RhinoのコモンズUnitOfWorkのを使用して、私はこのようなエンティティを保存するためにRhinoのリポジトリ静的クラスを使用したい:
Repository<Car>.Save(new Car(Id = 1));
私はその後、使用してすぐにその呼び出しの後に実体を得ることができることを見つけます:
Car car = Repository<Car>.Get(1);
これは正常に動作します。しかし、私はこのようなサイのUnitOfWorkにNHibernateはLINQのプロバイダを使用する場合:
var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()
select rep).ToList();
私は空のリストを取得します。私が私はこのような車を出すことができる前にUnitOfWork.Current.Flush()を呼び出す必要がありそうです。舞台裏で、私は両方の検索方法は、仕事の同じセッション/ユニットを照会することを前提としていことを考えると、なぜ、私は理解していません。これは、すべてがデータベースに保存した後、あなたがUnitOfWork.Current.Flush()を呼び出す必要があることを意味するのでしょうか?自分自身をフラッシュする際にNHibernateはうまくできないようにする必要があり?それとも私が何かを誤解しています!
解決
オーケー、それはそうです、そのセッションのキャッシュを使用することができますリポジトリに呼び出して取得するので、キャッシュに保存された車を「見る」ことができますが。
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
})
または[トランザクション]であなたの方法を飾るとATMを使用しています。これは、その後のLINQクエリは、最新のデータを見ることになることを確認します。
他のヒント
、あなたはそのオブジェクトを追跡し、次のフラッシュで、データベースへの変更を同期するために、リポジトリが保持しているセッションに通知されます。あなたはセッションをフラッシュするまでは、データベースは変更されません。オブジェクトは、しかし、セッション・キャッシュの一部になるんし、そう取得(1)によって返されます。
あなたは、コレクションを移入するクエリを実行すると、、セッションは、それがすでにそれらの結果をキャッシュしている場合を除き、結果を得るためにデータベースを照会します。 <ストライキ>あなたはまだ、データベースを更新していないので、あなたがセッションに追加カーは、結果セットの一部ではありません。スト>(< - おそらく間違った)。私が正しくドキュメントを読んでいる場合は、両方のクエリその結果、保存()されたエンティティは、セッション(最初のレベル)キャッシュに追加する必要があります。それは必ずしもquerystatement.List()
が...私が起こって正確に何のまわりで私の頭をラップ苦労を抱えているDBの結果を追加した後にキャッシュを照会することを意味するものではありません。
余談として、私はあなたが自動フラッシュするセッションを設定することができると信じて、私はマニュアルを確認する必要があると思います。
UPDATE:
私はここで何が起こっているか見るかもしれないと思います。デフォルトのセッションはFlushMode
あるAuto
が、RhinoのUnitOfWork.Start()
Commit
セッションは、オートフラッシュ明示的に呼び出すFlush()
またはトランザクションをコミットしませんしない限り意味し、FlushMode = Auto
するように設定してセッションを作成します。 Session.Find
のUnitOfWork.CurrentSession.FlushMode = FlushMode.Auto;
では、NHibernateのは、(時には?)返されるから古いデータを防ぐために問い合わせる前にセッションをフラッシュします。私が正しい場合は、あなたのDBのトランザクションは次のようになります。
SELECT * FROM Car
INSERT INTO Car (...) VALUES (...)
それオートフラッシュは、私が読んだ文書/ブログから少しあいまいなようだときに...最も一般的な答えは、それが<=>と、それは「時々」ものの<=>が古いデータを返さないことを保証をフラッシュすることです。 NHibernateはLINQのは、実際には基準クエリを作成するので、それは(多分これが修正されました...それは知ることは難しい)、オートフラッシュをトリガしない可能性があります。
あなたはすぐにあなたの保存の結果を取得したいので、だから、あなたのケースでは、あなたの保存した後にフラッシュしたいと私には思えます。あなたが唯一のエンティティを更新した作業の小さな単位では、単一の(コミット)罰金だろう。たぶん<=>トリックを行うが、UOW工場を明示的にコミットするモードを設定しているという事実は、本当にあなたのUOW境界について考えるようにあなたを励ましているように見えるでしょう。
スチュアートチャイルズのおかげで、私は彼が問題はNHibernateはLINQのプロバイダであってもよいこと権利である疑いがあります。私はそれが舞台裏で何をするかわからないんだけど、それはそれは私がLINQクエリは、それを「見る」になる前に、保存リポジトリをフラッシュする必要が理にかなっていない場合には、別のセッションを使用する場合があります。ソースコードを見て、私はそれを理解しようと、私の頭を溶かすだろうと言われました!
時間