12

CQRS とドメイン イベントの概念を使用したドメイン モデルでアプリケーションを構築しています (ただし、イベント ソーシングはなく、単純な古い SQL のみです)。SomethingChanged 系のイベントでは問題ありませんでした。次に、SomethingCreated イベントの実装に行き詰まりました。

ID主キーを持つテーブルにマップされるエンティティを作成すると、エンティティが永続化されるまでIDがわかりません。エンティティは永続性を無視するため、エンティティ内からイベントを発行する場合、ID は不明です。context.SaveChanges() を呼び出した後にのみ魔法のように設定されます。では、どのように/どこに/いつ Id をイベント データに入れることができますか?

私は考えていました:

  • イベントにエンティティへの参照を含めます。これはドメイン内では機能しますが、イベント/メッセージによって通信する複数の自律システムを備えた分散環境では必ずしも機能しません。
  • SaveChanges() をオーバーライドして、発行のためにキューに入れられたイベントを更新します。しかし、イベントは不変であることを意図しているため、これは非常に汚いようです。
  • ID フィールドを取り除き、エンティティ コンストラクターで生成された GUID を使用します。これは最も簡単かもしれませんが、パフォーマンスが低下し、デバッグやクエリなどの他の作業が難しくなる可能性があります ( 、where id = 'B85E62C3-DC56-40C0-852A-49F759AC68FB'いいえなど)。これは、多くのサンプル アプリケーションで見られるものです。MINMAX
  • ハイブリッド アプローチ - ID はそのままにして、主に外部キーとより高速な結合に使用しますが、アプリケーションのリポジトリからエンティティをプルする一意の識別子として GUID を使用します。
4

1 に答える 1

10

個人的には、特に数値 ID が問題を引き起こすマルチユーザーの分散環境では、一意の識別子の GUID が好きです。そのため、データベースで生成された ID 列/プロパティを使用することはなく、この問題は解消されます。

それ以外では、CQRS に従っているので、間違いなく CreateSomethingCommand とそれに対応する CreateSomethingCommandHandler があり、新しいインスタンスを作成し、リポジトリを使用して (context.SaveChanges を介して) 新しいオブジェクトを永続化するために必要な手順を実際に実行します。ドメイン オブジェクト自体ではなく、ここで SomethingCreated イベントを発生させます。

1 つは、コマンド ハンドラーがデータベース操作の完了を待機し、ID 値を取り出し、オブジェクトを更新してからイベントで ID を渡すことができるため、これで問題が解決します。しかし、より重要なことは、オブジェクトが「作成された」のはいつなのかという難しい問題にも対処できることです。

コンストラクターでドメイン イベントを発生させることは、コンストラクターが無駄がなく、単純に初期化を実行する必要があるため、悪い習慣です。さらに、モデルでは、ID が割り当てられるまでオブジェクトは実際には作成されません。これは、コンストラクターの実行後に追加の初期化手順が必要であることを意味します。複数のステップがある場合、実行順序を強制しますか (別のアンチパターン)、それともすべてのステップが完了したことを認識するために各ステップにチェックを入れますか (ああ、臭い)? うまくいけば、これがどのように急速に手に負えなくなるかがわかります。

したがって、コマンド ハンドラーからイベントを発生させることをお勧めします。(注: GUID 識別子に切り替えた場合でも、コンストラクターからイベントを発生させてはならないため、このアプローチに従います。)

于 2012-07-02T16:34:54.687 に答える