1. ホーム
  2. .net

[解決済み] NHibernate ISession Flush。いつ、どこで、なぜそれを使うのか?

2022-04-15 22:45:04

質問

私が徹底的に混乱することのひとつは session.Flush と併用し session.Commitsession.Close .

時々 session.Close は、例えば、私が必要とするすべての変更をコミットします。私は、トランザクションや、いくつかの作成/更新/削除を伴う作業単位がある場合、コミットを使用する必要があることを知っています。

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

どなたか、いつどこでFlushを使うか、良いガイドラインをお持ちの方はいらっしゃいませんか?NHibernateのドキュメントをチェックアウトしましたが、まだ明確な答えが見つかりません。

どのように解決するのですか?

簡単に説明します。

  1. 常にトランザクションを使用する
  2. 使用しない Close() 代わりに、呼び出しを ISession の内部で using ステートメントまたは ISession のライフサイクルを別の場所で管理します。 .

から ドキュメント :

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

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

SQL文は以下の順序で発行されます。

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

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

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

デフォルトの動作を変更し、フラッシュが発生する頻度を少なくすることも可能です。その場合 FlushMode クラスは3つの異なるモードを定義しています:コミット時にのみフラッシュする(そしてNHibernateの ITransaction API が使用されている場合)、説明されているルーチンを使って自動的にフラッシュする、または Flush() が明示的に呼び出されます。最後のモードは、長く続く作業単位に有効です。 ISession を長時間開いたままにしておくと、接続が切れる。

...

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

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

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

セッションをフラッシュする

を使用している場合は ITransaction APIでは、このステップを気にする必要はありません。トランザクションがコミットされるときに暗黙のうちに実行されます。そうでない場合は 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() はそれをプールに戻す。