2011-02-10 8 views
4

私は次のことを達成する方法を理解しようとしている:ドメイン駆動設計:集約ルートごとのリポジトリ?

User can have many Websites 

私は、ユーザーに新しいウェブサイトを追加する前に行うために必要なもの、ウェブサイトのURLを取得し、その意志メソッドに渡すことですウェブサイトがすでにデータベースに存在するかどうか(別のユーザが同じウェブサイトに関連付けられているかどうか)、または新しいレコードを作成するかどうかを確認します。 < =これは、新しいサムネイルを作成するか、既存のサムネイルを使用するかによって異なります。

問題は、リポジトリが集約ルートであることです。これは、私が上記で説明したことを実行することを意味しますか? - I 最初にデータベース内のすべてのユーザーを取得し、同じURLを持つWebサイトレコードがどこにあるかをチェックするforeach look with ifステートメントを実行しますが、これは無限で遅いプロセスになります。

答えて

2

どのリポジトリ手法を使用していても、何らかの方法で基準を指定できる必要があります。したがって、該当するウェブサイトに関連付けられたユーザーを検索します。ユーザーが何も返されない場合、そのウェブサイトは使用されていません。

たとえば、次のシグネチャを使用してメソッドを追加するかもしれない(またはあなたがdescribed in this articleとしてクエリオブジェクトを渡すと思います):

:メソッドは次のように多かれ少なかれSQLを生成する必要があります

User GetUser(string hasUrl); 

select u.userId 
from User u 
join Website w 
on  w.UserId = u.UserId 
where w.Url = @url 

これは、Websiteテーブルを直接クエリするほど効率的です。すべてのユーザーとウェブサイトのレコードをメモリに読み込む必要はありません。あなたのリレーショナル・データベースが大変な作業をして、リポジトリー実装(またはオブジェクト・リレーショナル・マッパー)が翻訳を処理できるようにします。

+0

はい、ただし、特定のURLを持つWebサイトに関連付けられたユーザーを検索するには、Webサイトがユーザーなしで存在しない場合(1対多) – ebb

+0

@ebb、私はちょうど 'u.UserIdUserIdからw.UserId = u.UserId w.Url = @ url'を選択するだけです(しかし、あなたのリポジトリのイディオムを仲介します基準を指定する)。 –

+0

@Jeff Sternal、あなたは私が間違っていると思う。同じURLの新しいWebサイトを追加してそれをユーザーに関連付ける前に、データベースのANYユーザーに同じURLのWebサイトレコードが関連付けられているかどうかをチェックしたいと思います。 – ebb

0

1つの戦略は、制約を検証できるサービスを実装することです。

public interface IWebsiteUniquenessValidator 
{ 
    bool IsWebsiteUnique(string websiteUrl); 
} 

あなたは、あなたはそれが私にはわからないが、私はドメインを介して行くことについて心配することはないことをお勧めの要因に依存するどのように行う、それを実装する必要があります。シンプルにしましょう。ちょうどクエリです(* - これを下部に追加します)。

public class WebsiteUniquenessValidator : IWebsiteUniquenessValidator 
{ 
//..... 
} 

次に、それが必要な方法に「注入」します。私はドメインの外部からドメインオブジェクトに提供するので、 "注入"と言うが、コンストラクタパラメータではなくメソッドパラメータで行う(私たちのエンティティをIoCコンテナによってインスタンス化する必要を避けるため) )。それは、サービスクラスまたはCommandHandlerだ場合 - - そのユニークさバリデータ依存性を提供することができ、あなたのユーザーとそのリポジトリの消費者が何であれ

public class User 
{ 
    public void AddWebsite(string websiteUrl, IWebsiteUniquenessValidator uniquenessValidator) 
    { 
     if (!uniquenessValidator.IsWebsiteUnique(websiteUrl) { 
      throw new ValidationException(...); 
     } 

     //.... 
    } 
} 

。それはUserRepositoryを消費しますので、この消費者はすでにによって、IoCの通って上に配線する必要があります

public class UserService 
{ 
    private readonly IUserRepository _repo; 
    private readonly IWebsiteUniquenessValidator _validator; 

    public UserService(IUserRepository repo, IWebsiteUniquenessValidator validator) 
    { 
     _repo = repo; 
     _validator = validator; 
    } 

    public Result AddWebsiteToUser(Guid userId, string websiteUrl) 
    { 
     try { 
      var user = _repo.Get(userId); 
      user.AddWebsite(websiteUrl, _validator); 
     } 
     catch (AggregateNotFoundException ex) { 
      //.... 
     } 
     catch (ValidationException ex) { 
      //.... 
     } 
    } 


} 

*私は検証を簡単に作るとドメインを避け述べました。

ドメインを構築して、データの変更に伴う複雑な動作をカプセル化します。

これは、データの変更に関する要件がデータのクエリに関する要件と大きく異なることを示しています。

これは、書き込みシステムを強制的に読み込みしようとしているため、これは苦労しているようです。

これらの痛みを緩和するために、書き込み側からドメインからのデータの読み取りを分離することは可能です。

CQRSは、この手法に与えられた名前です。私はCQRSの文脈でDDDを見たら、電球の束が一度クリックされたと言うでしょう。 CQRSの概念を理解しようとすることを強くお勧めします。

+0

"強制的に読み込みシステムを通過しようとしているため、あなたが経験している痛みポイント" - よく置いてください!この正確な問題を中心に、DDDに関する懐疑的な質問の90%が回っているようです。 (これを言って、私は集計のリポジトリ内でこの特定の問題を解決するのが難しいとは思わない) –

+0

このタイプの検証「パターン」とは正確に何を呼んでいますか?以前にエンティティメソッドに注入された検証クラスは見ていませんでした。これはドメインエンティティを汚染しませんか?つまり、この場合ではありませんが、複雑な検証がたくさんあります。この方法ですべての検証を処理しますか?また、CQRSについて。確かに面白いですが、あなたのシステムがエンタープライズ・イズではない場合は、非常に多くの作業のようです。グレッグ・ヤングは、あらゆる種類の方法で拡張されるのは非常に大きなシステムのためだと言っています。どう思いますか?私が間違っているなら私を訂正してください。 –

+0

私は実際には "パターン"とは何も呼んでいません。非効率的でも、集約したルートやリポジトリのいくつかの法律に違反することなく、必要な場所で正しいデータへのアクセスを提供する方法の緊張を解消する方法の1つであるように思えました。別の方法は、DB内の一意制約を使用して例外をキャッチすることです。 –

1

あなたのモデルには根本的な問題があると思います。私が正しく理解していれば、WebサイトはUser集約グループの一部です。つまり、ウェブサイトのインスタンスにはグローバルスコープがなく、ユーザーに所属している場合にのみ意味があります。

しかし、ユーザーが新しいWebサイトを追加する場合は、新しいWebサイトを作成する前に、まず「Webサイトがデータベースに存在するかどうか」を確認する必要があります。つまり、ウェブサイトには実際にはグローバルスコープがあります。それ以外の場合は、ユーザーが新しいWebサイトを要求したときはいつでも、そのWebサイトをそのユーザーのスコープ内で意味のある特定のユーザー用の新しいWebサイトを作成します。ここでは、多くのユーザーの範囲で共有され、したがって意味を持ち、したがってユーザー集約の一部ではないWebサイトがあります。

モデルを修正すると、クエリが難しくなります。

関連する問題