11

CQRS は非常に理にかなっています。ただし、変更追跡を提供する ORM を使用するアプローチとは相容れないようです。オブジェクトを RO として取得するためのクエリ用の「チャネル」が 1 つある場合、追跡する変更はありません。CUD+ コマンド用の別のチャネルがある場合、軽い DTO を使用した RPC アプローチのほうが多く、自己追跡エンティティを送信して下位層でマージします。

これら 2 つのアプローチ (CQRS / ORM + STE) をどのように調和させることができますか?

4

2 に答える 2

8

CQRS アプリケーションを構築する一般的な方法は、コマンド ハンドラー内のドメイン モデルに基づいて動作することです。

コマンド DTO を送信し、ハンドラーでドメイン オブジェクトのメソッドを呼び出します (ドメイン エンティティのプロパティを設定しないでください。これは主要なアンチパターンです)。

ドメイン オブジェクトのメソッドは、ドメインの内部状態の変更を担当します。

その時点で、ORM はドメイン オブジェクトの内部状態への変更を永続化する責任があります。

CQRS アプリケーションを構造化するこの方法では、イベント ソーシングは使用されませんが、ORM とセルフ トラッキング エンティティが使用されます。

これは非常に単純化された例です。

public class AccountController 
{
  [HttpPost]
  public ActionResult ChangePreferredStatus(Guid accountId, bool isPreferred)
  {
    if (isPreferred) {
      // in response to user action, our controller commands our application to carry out an operation/state transition
      Bus.SendCommand(new MakeAccountPreferredCommand(accountId));
    }
  }
}

public class MakeAccountPreferredCommandHander : IHandle<MakeAccountPreferredCommand>
{
  public void Handle(MakeAccountPreferredCommand command) 
  {
    using (var uow = new UnitOfWork()) {
      var account = accountRepository.Get(command.AccountId);
      if (account != null) {
        // we tell the domain what we want it to do, we DO NOT fiddle with its state
        account.MakePreferred();
      }
      uow.Accept(); // accepting the uow saves any changes to self-tracked entities
    }
  }
}

public class Account : SelfTrackedEntity
{
  private Guid accountId;
  private bool isPreferred; // ORM tracked *private* state

  public void MakePreferred() 
  {
    // entities are responsible for their own state and changing it
    ValidateForMakePreferred();
    isPreferred = true;
    RaiseEvent(new AccountMadePreferredEvent(accountId));
  }
}
于 2011-04-08T19:25:40.347 に答える