2012-12-19 9 views
12

NHibernateにdynamic-insert/dynamic-updateを使用しない理由はありますか?私が尋ねる唯一の理由は、私が構成しなければならないものとしてではなく、デフォルトとして有効にしたいものであるように思われるということです。NHibernate動的更新の短所?

これらの動的プロパティを使用する際に注意すべき点がありますか?

答えて

23

一部のエンティティでは、動的更新によって無効な状態が作成されることがあります。 BooleanプロパティAと論理的に依存するIntegerプロパティBを持つClassがあるとします。プロパティATrueの場合、プロパティBは負数にしかなりませんが、プロパティAFalseの場合、プロパティBは正数にしかなりません。

たとえば、2人のユーザーが両方とも、指定された期間内にこのクラスのインスタンスと対話するとします。オフを開始するには、ユーザーがアリスとボブは両方A =真の初期値で、データベースからこのクラスを実体とB = -50

Database Alice  Bob 
A: True A: True  A: True 
B: -50  B: -50  B: -50 
VALID  VALID  VALID 

ユーザーAliceは125にFalseBAを変更し、それをコミットデータベースに転送します。そして、それをデータベースにコミットし、

Database Alice  Bob 
A: False A: False A: True 
B: 125  B: 125  B: -50 
VALID  VALID  VALID 

ユーザーボブはAを変更しませんが、-75にBを変更します。今、私たちはこのような状況を持っています。動的更新がオンの場合、NHibernateはBobがBを-75に変更したことを認識し、Bの値のみを編集する動的更新を発行します。 Aが真でない限り、Bが否定的にならないようにサーバー上でSQL検証を行った場合は、ここでSQLエラーが発生しますが、SQLテーブルにすべてのビジネスロジックを再現していないとしましょう。結果は次のとおりです。

Database Alice  Bob 
A: False A: False A: True 
B: -75  B: 125  B: -75 
INVALID VALID  VALID 

アリスとボブの両方に有効な状態がありますが、データベースは現在無効な状態です。ユーザーチャーリーは一緒に来て、このレコードを具現化しようとします:NHibernateのは、あなたのクラスの新しいインスタンスのBプロパティを設定しようとしたとき

Database Alice  Bob  Charlie 
A: False A: False A: True A: False 
B: -75  B: 125  B: -75 B: -75 
INVALID VALID  VALID  INVALID 

チャーリーはおそらく、あなたのアプリケーションからの検証エラーになるだろう。

したがって、論理的に依存するプロパティがある場合は、このような状況を回避するための戦略が必要です。 1つの可能性は、単にこのエンティティに対してselect-before-updateを有効にすることです。これにより、追加のデータベース呼び出しが発生し、パフォーマンスが少し低下する可能性があります。もう一つは、NHibernateでバージョニングを利用することです。これは、Bobがレコードを保存しようとすると、NHibernateの挿入クエリは書き込みをトリガーせず、(正常に処理できる)古いデータ例外をスローしないことを意味します。また、データベース内のクラスの論理的な要件をコード化することもできますが、データベースとプログラムの両方に、時間の経過と同じコード化された要件があることを確認するためには注意が必要です。要件が変更されたときに変更を加えることは、必ずしも価値のあるオーバーヘッドではありません。

要するに、多くの状況では、開発者は動的更新の詳細を注意深く処理する必要があります。そのため、デフォルトではオンになっていません。これをオンにすると、エンティティの部分的な更新が問題を引き起こす可能性があるかどうかを検討します。もしそうなら、その問題を防ぐために推奨した緩和戦略の1つを使用してください。

+0

非常に有益です。私は選択前の更新についても知らなかった。間違いなく心に留めておきます。 – Sam

+2

この例では、エンティティが無効な状態になっているときにアプリケーションが変更をコミットできるようになりました。クラスは、ビジネスルールが強制されるようにそれらのプロパティへのアクセスをカプセル化し、トランザクションがコミットされる前にエンティティを検証する必要があります。私はこれが動的な更新とは関係ないことを知りません。 –

+0

ここにレッスンがありません:ボブのエンティティのコピーが無効な状態ではありませんでした。エンティティは、プロパティAの永続化された値によってその値が無効になるという情報を持たずに、動的更新によってプロパティBの値が変更されたときにのみ無効になりました。 –

5

ダイナミックな挿入と更新は、NHibernateがキャッシュする代わりにSQLを毎回構築する必要があるため、わずかなパフォーマンスコストがあります。私は、データベース側にコストがあるかどうかはわかりません。動的な挿入と更新は、トラブルシューティングとプロファイリングに非常に便利です。私が意味のあるパフォーマンス・ヒットを測定できたなら、私はそれを開発時にオンにし、プロダクションでオフにします。

リスナーとインターセプタに関する問題が発生することがあります(this questionを参照)。

私は問題なくNHibernateアプリケーションでそれをオンにしました。私の答えはいいえ、それを使用しない正当な理由はありません。

+0

キャッシングに関するあなたのコメントが不思議です。 log4netを使用して生成されたSQLを見ると、依然としてパラメータ化されたクエリが使用されているようです。それらはまだラインのどこかにキャッシュされませんか?また、動的クエリをオフにしておかないと、変更されていないフィールドを更新してパフォーマンスが低下しますか?それとも、費用は無視できるのでしょうか?フィードバックをお寄せいただきありがとうございます。 – Sam

+2

NHibernateは静的なクエリフォーマットをキャッシュすることができるので、クエリを作成するだけで空白が埋められます。動的クエリでは、毎回クエリを構築する必要があります。すべてのフィールドが更新されると、データベースに依存します。いくつかの要素がありますが、私の意見や経験は、動的な挿入と更新の使用をお勧めしています。 –