189

私を完全に混乱させるものの1つは、、、およびsession.Flushを組み合わせて使用​​することです。session.Commitsession.Close

時々session.Close動作します、例えば、それは私が必要とするすべての変更をコミットします。エラーが発生した場合にロールバックを選択できるように、トランザクションまたは複数の作成/更新/削除を伴う作業単位がある場合は、コミットを使用する必要があることを知っています。

しかし、時々私は背後にあるロジックに本当に悩まされsession.Flushます。フラッシュが続く例を見てきましたsession.SaveOrUpdate()が、フラッシュを削除すると、とにかく正常に動作します。Flushステートメントでセッションがタイムアウトしたというエラーが発生することがあり、それを削除することで、そのエラーが発生しないようにしました。

フラッシュをどこで、いつ使用するかについて、誰かが良いガイドラインを持っていますか?これについてNHibernateのドキュメントを確認しましたが、それでも簡単な答えは見つかりません。

4

4 に答える 4

238

簡単に言うと:

  1. 常にトランザクションを使用する
  2. を使用しないでください。代わりに、ステートメント内でClose()呼び出しをラップするか、ISession のライフサイクルを別の場所で管理してくださいISessionusing

ドキュメントから:

ISessionは、ADO.NET 接続の状態をメモリに保持されているオブジェクトの状態と同期するために必要な SQL ステートメントを時々実行します。このプロセスであるフラッシュは、デフォルトで次の時点で発生します。

  • Find()orのいくつかの呼び出しからEnumerable()
  • からNHibernate.ITransaction.Commit()
  • からISession.Flush()

SQL ステートメントは、次の順序で発行されます。

  1. を使用して対応するオブジェクトが保存されたのと同じ順序で、すべてのエンティティの挿入ISession.Save()
  2. すべてのエンティティの更新
  3. すべてのコレクションの削除
  4. すべてのコレクション要素の削除、更新、および挿入
  5. すべてのコレクションの挿入
  6. すべてのエンティティの削除。対応するオブジェクトが削除されたのと同じ順序でISession.Delete()

(例外は、ネイティブ ID 生成を使用するオブジェクトが保存時に挿入されることです。)

明示的な場合を除いてFlush()、セッションが ADO​​.NET 呼び出しを実行するタイミングについてはまったく保証されず、それらが実行される順序のみが保証されます。ただし、NHibernate はISession.Find(..)メソッドが古いデータを返さないことを保証します。また、間違ったデータを返すこともありません。

デフォルトの動作を変更して、フラッシュの発生頻度を下げることができます。クラスは 3 つのFlushMode異なるモードを定義します: コミット時にのみフラッシュする (および NHibernate ITransactionAPI が使用されている場合のみ)、説明されたルーチンを使用して自動的にフラッシュする、Flush()明示的に呼び出されない限りフラッシュしない。ISession最後のモードは、 が長時間開いたまま切断されたままになる、長時間実行される作業単位に役立ちます。

...

このセクションも参照してください。

セッションの終了には、次の 4 つの段階があります。

  • セッションをフラッシュする
  • トランザクションをコミットする
  • セッションを閉じる
  • 例外を処理する

セッションのフラッシュ

APIを使用している場合ITransactionは、この手順について心配する必要はありません。トランザクションがコミットされると暗黙的に実行されます。それ以外の場合は、呼び出しISession.Flush()て、すべての変更がデータベースと同期されていることを確認する必要があります。

データベース トランザクションのコミット

NHibernate ITransaction API を使用している場合、これは次のようになります。

tx.Commit(); // flush the session and commit the transaction

ADO.NET トランザクションを自分で管理している場合はCommit()、ADO.NET トランザクションを手動で行う必要があります。

sess.Flush();
currentTransaction.Commit();

変更をコミットしない場合:

tx.Rollback();  // rollback the transaction

また:

currentTransaction.Rollback();

トランザクションをロールバックする場合は、NHibernate の内部状態が一貫していることを確認するために、現在のセッションをすぐに閉じて破棄する必要があります。

ISession を閉じる

への呼び出しISession.Close()は、セッションの終了をマークします。Close() の主な意味は、ADO.NET 接続がセッションによって放棄されることです。

tx.Commit();
sess.Close();

sess.Flush();
currentTransaction.Commit();
sess.Close();

独自の接続を提供した場合はClose()、それへの参照が返されるため、手動で接続を閉じるか、プールに返すことができます。それ以外の場合Close()は、それをプールに返します。

于 2008-09-04T11:58:27.247 に答える
14

NHibernate 2.0 以降、DB 操作にはトランザクションが必要です。したがって、ITransaction.Commit()呼び出しは必要なフラッシュを処理します。なんらかの理由で NHibernate トランザクションを使用していない場合、セッションの自動フラッシュは行われません。

于 2008-09-04T17:17:08.837 に答える
1

ISession は、ADO.NET 接続の状態をメモリに保持されているオブジェクトの状態と同期するために必要な SQL ステートメントを実行することがあります。

そしていつも使う

 using (var transaction = session.BeginTransaction())
 {
     transaction.Commit();
 }

この変更よりも変更がコミットされてデータベースに保存された後、transaction.Commit(); を使用します。

于 2014-03-05T09:25:26.057 に答える
0

session.Flush() がないと失敗する私のコードの例を 2 つ示します。

http://www.lucidcoding.blogspot.co.uk/2012/05/ching-type-of-entity-persistence.html

この最後に、ID の挿入をオンに設定し、エンティティを保存してからフラッシュし、ID の挿入をオフに設定するコードのセクションを確認できます。このフラッシュがないと、ID 挿入のオンとオフを設定してからエンティティを保存しているように見えました。

Flush() を使用すると、何が起こっているのかをより細かく制御できます。

別の例を次に示します。

TransactionScope内でNServiceBusメッセージを送信する

この理由は完全にはわかりませんが、Flush() はエラーの発生を防ぎました。

于 2012-11-06T13:38:48.130 に答える