2011-09-21 9 views
11

ここに私の質問につながる本当の例があります:ArticleId、コメントテキスト、電子メールアドレスを持つAddCommentToArticleCommandがあります。このコマンド:ドメインエンティティの変更を保存する

  • は、記事が存在する場合
  • (ドメインエンティティである)の記事を取得するために記事のリポジトリを使用して、それが記事にコメントを追加しarticle.AddComment(commentText、EMAILADDRESS)は、呼び出し、それができないときに例外をスローする(無効な電子メール形式、記事が閉じられている、コメントが埋め込まれていない、または長すぎるなど...)
  • しかし、今は追加されたコメントを保存することが最善の方法はわからない?

articleRepository.Save(article)のような操作を行う必要がありますか?しかし、コメントだけが追加された場合は、どうして記事を保存しなければならないのですか?または、記事の保存のみを行うarticleRepository.SaveComment(コメント)のようなことをすることはできますか?または、あなたはここにどのようなアプローチをしますか?

ありがとうございます!

答えて

8

MattDaveyとしてポイントうち、DDDにあなたは通常、約Aggregateライフサイクルを考えていません:コードサンプル:十分に明らかにされて、私は

EDIT概念的なものを:)説明ではあまりよくありませんよ永続性の問題。集合体の中期と終わりは対応するRepositoryによって処理されます。あなたの特定の質問について:

しかし、今では、追加されたコメントを保存することが最善の方法は何か分かりません。

これを処理するための最良の方法は、信頼性の高いORMを見つけると、このORMを使用して

articles.MakePersistent(article) 

リポジトリメソッドを実装することです。良いORMはUnitOfWorkを実装し、ドメインオブジェクトを制約することなく、ダーティトラッキング、遅延ロード、その他の永続性関連の問題を含みます。 ORMは、集計を保存するときにSQL INSERT/UPDATEを必要としないようにする方法を知っています。あなたのドメインオブジェクトは、できるだけ永続的な無知でなければなりません。たとえば、NHibernateがオブジェクトに置く唯一の制約は、プライベートのデフォルトのコンストラクタを持つ必要があることです。それ以外の単純なPOCOオブジェクトは、すべての永続性の問題を認識できません。クリアするだけで、ドメインオブジェクトにはIsTransientまたはIsDirtyフラグを設定しないでください。そして、これらのフラグを使用するコードを書くことが見つかった場合は、reinveting the wheelです。

+2

私はあなたがすでに存在することをしていることを実感したので、あなたのコメントを私は助けてくれました。だから私はアプローチを変えました:私はエンティティフレームワークをコードで最初に使用します。作業パターンの単位を実装しました。だから、EFの文脈は私のために変更を維持しています。フィードバックをお寄せいただきありがとうございます! –

+0

@Dmitry +1これは非常に有効なポイントです。私の特別な状況では、使用されているORMの機能(ORMではないかもしれません)について何も仮定することはできませんので、ドメイン内での変更の追跡などを実装することは意味があります。 ORM実装に十分に縛られていると、確実にその機能を活用できますが、それはもちろん意味があります:) – MattDavey

+0

実際、私のドメインはORMなどに依存していません。それはタマネギの建築の中心です。その周りに構築される作業単位は、ORMに依存し、変更トラッキングにそのコンテキストを使用します。しかし、ドメインにはドメインロジックしかありません。 –

1

DDDでは、集約ルート全体からコンポジション階層全体を取り出し、単一のエンティティとして扱うことがよくあります。したがって、その考え方を採用すると、"コメントだけが追加された場合は記事を保存するのはなぜですか?"では、記事全体が変更され、データベース内の記事の表現が古くなっているように見えます。理想的には、データベース内の全構成階層を置き換えることができます(ただし、これは正常に動作するドキュメントデータベースを使用します)。これにより、リレーショナルDBのパフォーマンスに問題が発生する可能性があります。

この場合、エンティティの構成全体にわたってリポジトリをスキャンし、ルートを集約し、各コンポーネントで何をすべきかをインテリジェントに決定することができます。訪問者のパターンを使用して、コメントオブジェクトを繰り返し処理し、一時的な/汚いかどうかに応じて、挿入または更新を行うか、またはそのままにするかを決定できます。

私はCRUDについては、

// In ArticleRepository... 
public void Save(Article article) 
{ 
    // IsTransient (as opposed to IsPersistant) means "has not yet been saved"... 
    if (article.IsTransient) 
    { 
     DB.InsertArticle(article); 
     // Inserting the article also inserts any comments/sub components... 
    } 
    else 
    { 
     // IsDirty means "has been modified since it was taken from the DB"... 
     if (article.IsDirty) 
     { 
      DB.UpdateArticle(article); 
     } 

     foreach(var comment in article.Comments) 
     { 
      if(comment.IsTransient) 
      { 
       DB.InsertComment(article.Id, comment); 
      } 
      else 
      { 
       if (comment.IsDirty) 
       { 
        DB.UpdateComment(comment); 
       } 
      } 
     } 
    } 
} 
+0

ありがとうございます!だから私は、プロパティが変更された場合、エンティティがこれらのIsTransientプロパティとIsDirtyプロパティを更新する必要があることを意味します。リポジトリはエンティティを保存した後にそれらをリセットする責任がありますか? –

+0

実際、System.ComponentModel.IChangeTrackingインターフェイスをチェックしてください。 IsTransient/IsPersistantは時々主キー値の欠如/存在によって導かれることがあります。 – MattDavey

+0

エンティティの初期化時にISupportInitializeを実装することが多いエンティティでは、プロパティを変更してもエンティティがダーティになりません変更されたイベントなど)。これは非常に便利かもしれません:) – MattDavey

関連する問題