NHibernate セッション上で Unit of Work パターンを使用するのはなぜですか?
-
13-09-2019 - |
質問
NHibernate によってすでに提供されているものの上に UoW 実装を作成するのはいつですか?実際の例はありますか?
解決
あなたが説明している作業単位はすでに NHibernate によって提供されているため、そのような作業単位を実行する理由はありません。
WCF サービスにあるものは、現在の作業単位のアプリケーションで重要な情報を含む、より高いレベルの作業単位です。これには、NHibernate ISession の抽象化が含まれます。分解すると、コードは 3 つのカテゴリに分類されます。
作業単位を処理する必要があるコード。誰がその作業単位を支援するかは関係ありません。NHibernate、iBatis、またはカスタム ORM である可能性があります。コードで行う必要があるのは、ロード、ロールバック、保存などだけです。そのために使用されるメカニズムについては気にしませんし、気にする必要もありません。
NHibernate 固有の処理を行うため、ISession を直接処理する必要があるコード。通常、これは作成する必要がある複雑なクエリに関係します。
作業単位で実行されていることを認識したり、ISession にアクセスしたりする必要はありません。この議論の一環として、これは完全に無視して構いません。
1でコードを書きながら。ISession に対してのみ機能する可能性があります。私たちの好みは、直接制御していないものや変更される可能性のあるコード内の要素を抽象化することです。これには 2 つの理由から価値があります。
私たちが始めたとき、NHibernate で 100% 売れたわけではありませんでした。iBatis か何かのカスタムを検討していました。明らかに、これはもう問題ではありません。
チーム全体は NHibernate の専門家ではありませんし、私たちも彼らに専門家になってもらいたいとは思っていません。ほとんどの場合、人々はカテゴリー 1 に当てはまるコードを作成します。そして彼らが知っているのは私たちの作業単位だけです。カテゴリ 2 でコーディングする場合。NHibernate をよく理解しているチームの人々によって書かれなければなりません。
最後になりますが、あなたが話しているような種類の作業単位は必要なく、より高いレベルの作業単位が多くの価値を提供できると提案します。
他のヒント
作業インターフェイスの私の基本的な単位は、次のメソッドが含まれています - 初期化 - コミット - ロールバック - IDisposable.Dispose
私は、セッションおよびトランザクション管理の両方のためにそれを使用しています。 私は別のセッションスコープのために何度も何度もそのコードを記述する必要はありませんので、これは便利です。 (要求ごとの作業単位、一連の要求ごと、スレッドごと、など)
(すなわちカスケード)が正しく、すべてのマッピングを設定提供、あなたは特別な何かをする必要はありませんし、ISession
はうまくやるだろう。あなたは3層アプリケーションを書いている場合は、あなたが1つのトランザクションで実行したいデータベース操作を手動でシーケンスする必要があります。 「エンタープライズアプリケーションアーキテクチャのパターン」でファウラーの「リファレンス実装」は良い出発点となることができます:
class UnitOfWork...
public void registerNew(DomainObject obj) {
Assert.notNull("id not null", obj.getId());
Assert.isTrue("object not dirty", !dirtyObjects.contains(obj));
Assert.isTrue("object not removed", !removedObjects.contains(obj));
Assert.isTrue("object not already registered new", !newObjects.contains(obj));
newObjects.add(obj);
}
public void registerDirty(DomainObject obj) {
Assert.notNull("id not null", obj.getId());
Assert.isTrue("object not removed", !removedObjects.contains(obj));
if (!dirtyObjects.contains(obj) && !newObjects.contains(obj)) {
dirtyObjects.add(obj);
}
}
public void registerRemoved(DomainObject obj) {
Assert.notNull("id not null", obj.getId());
if (newObjects.remove(obj)) return;
dirtyObjects.remove(obj);
if (!removedObjects.contains(obj)) {
removedObjects.add(obj);
}
}
public void registerClean(DomainObject obj) {
Assert.notNull("id not null", obj.getId());
}