NHibernate によって既に提供されているものの上にいつ UoW 実装を作成しますか? 実際の例はありますか?
3 に答える
あなたが説明している作業単位は既に NHibernate によって提供されているため、そのような作業単位を実行する理由はありません。
WCF サービスにあるのは、現在の作業単位のアプリケーションで重要な情報を含む高レベルの作業単位です。これには、NHibernate ISession の抽象化が含まれます。分解すると、コードは 3 つのカテゴリに分類されます
作業単位を処理する必要があるコード。誰が作業単位を支援するかは問題ではありません。NHibernate、iBatis、またはカスタム ORM の可能性があります。コードで行う必要があるのは、ロード、ロールバック、保存などだけです。それを行うために使用されるメカニズムは気にしませんし、気にする必要もありません。
NHibernate 固有の処理を行っているため、ISession を直接処理する必要があるコード。通常、これは、作成する必要がある複雑なクエリに関係しています。
Unit Of Work で実行されていることや ISession にアクセスしていることを知る必要はありません。この議論の一部として、これは完全に無視できます。
1. のコードは ISession に対して機能する可能性がありますが、私たちの好みは、直接制御できないコードや変更される可能性のあるコード内のものを抽象化することです。これには 2 つの理由から価値があります。
私たちが始めたとき、NHibernate で 100% 販売されたわけではありませんでした。iBatisか何かのカスタムを考えていました。明らかに、これはもはや問題ではありません。
チーム全体が NHibernate のエキスパートではありません。ほとんどの場合、人々はカテゴリ 1 に当てはまるコードを書きます。彼らが知っているのは作業単位だけです。カテゴリ 2. のコードを作成する必要がある場合は、NHibernate をよく理解しているチームのメンバーによって作成されます。
最後に、あなたが話しているタイプの作業単位は必要ありません。より高いレベルの作業単位が多くの価値を提供できることをお勧めします。
私の基本的な作業単位インターフェイスには、次のメソッドが含まれています-初期化-コミット-ロールバック-IDisposable.Dispose
セッション管理とトランザクション管理の両方に使用します。さまざまなセッション スコープに対してコードを何度も記述する必要がないため、便利です。(リクエストごと、一連のリクエストごと、スレッドごとなどの作業単位)
すべてのマッピングを正しく設定 (つまり、カスケード) していれば、特別なことをする必要はなく、問題なく動作しますISession
。ただし、3 層アプリケーションを作成している場合は、単一のトランザクションで実行するデータベース操作を手動で順序付けする必要があります。「エンタープライズ アプリケーション アーキテクチャのパターン」にある Fowler の「参照実装」は、良い出発点になる可能性があります。
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());
}