23

このアプリケーションでは、ドメイン モデルで何かが変更されたときにドメイン イベントを発生させます。イベント ハンドラーによって実行されるタスクの一部は、イベントが発生したときに使用されたのと同じトランザクション内で実行する必要があり、他のタスクはこのトランザクションの外部で実行する必要があります。

例えば、

Orderline が Order エンティティに追加されると、OrderLineAdded ドメイン イベントが発生し、1 つのドメイン イベントがドメイン モデルの状態を変更します (したがって、同じトランザクションで実行する必要があります)。トランザクションが完了すると、UI を更新する必要があります。

この問題にどのように取り組みますか?

  1. トランザクション内で 1 つ、トランザクション外で 1 つの 2 つのイベントを発生させます。
  2. トランザクション内でイベントを発生させますが、イベント ハンドラーを使用して Async 要求を送信し、UI を更新しますか?

オプション 1 は、イベント名が何らかの形でトランザクション内またはトランザクション外であることを伝える必要があるため、紛らわしいように見えますが、オプション 2 では、ドメイン イベントのハンドラーは常に、トランザクション内から同期的に呼び出されると想定する必要があります。

たぶん、より良いアプローチがありますか?

4

2 に答える 2

21

同様の問題がありました。ドメイン モデルはイベントを発行していました (Udi Dahan がここで説明する手法を使用)。その後、何か問題が発生してトランザクションが後でロールバックされても、UI 関連のハンドラーが呼び出されることに気付きました。

これを修正するために、システムに別の役割、別の種類のイベント ハンドラーを導入しました。私はITransactionalEventHadnelerとを持っていINonTransactionalEventHandlerます。前者はメソッドですぐに同期的に呼び出されましたDomainEvents.Publish()。後者は、トランザクションがコミットされるとすぐに呼び出されるようにキューに入れられました (System.Transactions フックを使用)。このソリューションは問題なく機能し、非常に読みやすく、保守しやすいものでした。

于 2011-01-17T12:33:14.493 に答える
1

コードのすべての部分で同じアプローチに固執するだけで、両方のアプローチが良いと思います。

  1. 2 つ (またはそれ以上) のイベント ハンドラーが必要です。1 つはトランザクション スコープ内にあるドメイン モデルのコンテキスト用で、もう 1 つは UI などの補助コンテキスト用です。ドメイン コードは、コードの他の部分が何をするかを気にする必要はありません。ドメイン データの変更について通知するだけです。
  2. ドメイン コードのイベント ハンドラー メソッドは、UI または他のモジュールに非同期イベントを送信する場合があります。ドメイン イベントは同期する必要があります。そうしないと、トランザクション性を維持するために 2 フェーズ コミットが必要になります。

個人的には、オプション 2 の方が気に入っています。これは、ドメイン コードをクリーンに保ち、非同期通信を使用することでコアと他のモジュールが分離されるため、外部モジュールの問題がコアの動作を妨げないためです。一方、オプション 1 の方が有利な場合もあります。

于 2011-01-16T21:38:10.070 に答える