2016-10-03 4 views
0

私は現在、次のプロジェクトのアーキテクチャとパターンに取り組んでいます。私はDDDの使用を検討していますが、プロジェクトは中規模なので、コードの複製や全体的なメンテナンスの観点から可能な限りシンプルにしようとしています。DDD、エンティティフレームワークとエンティティマッピング

DB -> Domain -> Application -> Web API -> Clients 

DBアクセスのために、私はEFコア1.0を使用しています:

層は次のように、基本的にそれぞれの層が別のアセンブリで見えます。

ここで私はデータとドメインのクラスのクラスの私の現在の設計(簡略化)ですが、私はそれほど満足できません。

ドメイン:

class Task 
{ 
    private int State { get; set; } 
    private string Description { get; set; } 
    private int CreatedById { get; set; }    
} 

データ(EF):

class TaskData 
{ 
    public int State { get; set; } 
    public string Description { get; set; } 
    public int CreatedById { get; set; } 
    public User CreatedBy { get; set; } 
} 

理想的には私はORMと直接自分のドメインのエンティティを使用したいのですが、タスクおよびTaskDataは同一ではありません。タスクのエンティティでは、ナビゲーションプロパティCreatedByは必要ありません。私はIdだけで問題ないので、気にしないものでドメインを汚染したくありません。

データモデルでは、一部のレポートでナビゲーションプロパティを使用しているため、この結合は便利な場合があります。

ドメインエンティティを直接マッピングできない場合は、データレイヤでマッピングを行う必要があります。より具体的には、を経由してリポジトリで。手動マッパークラス。私のドメインエンティティにはパブリックゲッターとセッターがないので、プロパティベースでTaskDataをTaskエンティティにマップすることはできません。

これはパターンを記念するために私をリードし、私は単なるDTOのよ​​うだ新しいクラス、作成:

class TaskSnapshot 
{ 
    public int State { get; set; } 
    public string Description { get; set; } 
    public int CreatedById { get; set; } 
} 

をそして、私のオリジナルのタスクのエンティティは次のように今見える:あなたのよう

class Task 
{ 
    ...   
    public Task(TaskSnapshot snapshot) 
    { 
    this.State = snapshot.State; 
    this.Description = snapshot.Description; 
    this.CreateById = snapshot.CreatedById; 
    } 

    public TaskSnapshot ToSnapshot() 
    { 
    return new TaskSnapshot() 
    { 
     State = this.State, 
     Description = this.Description, 
     CreatedBy = this.CreatedBy }; 
    } 
} 

異なる目的の3つのクラスが必要ですが、作成と保守には非常に似ています。それは単にデータとドメインのレイヤーです。他の層でも「複製」が続きます。

新しいフィールドを追加する場合は、追加する場所をすべて覚えて、正しく割り当てる必要があります。チームの誰かがすべてのコードを更新することを忘れているので、これはバグにつながることがよくあります。私は何ができるか

  1. は、ドメインエンティティのゲッターとセッター公開するので、私はスナップショットを必要としないでしょう。 - >間違いなく!

  2. 不要なプロパティ(CreatedByナビゲーション)をタスクエンティティに追加し、ORMで直接使用します。 - >私はむしろそうしたくありません。

  3. データモデルにスナップショットクラスを変換し、ORMと共に使用します。 - >おそらくナビゲーションプロパティは気にしないでしょうが、それはデータモデルがドメインアセンブリの一部であることを意味します。 - >私は知らない、私はそれが好きではない。

私は効果的にクラスの数を減らすか、ドメインを損なうことなく、1位/マッパークラスにALL割り当て(マッピング)を集中することができる方法の推薦はありますか?

ありがとうございます。

+0

ちょうど質問 - まずコードを使用してみませんか?この方法で、データベースをドメイン層に直接マッピングできます。 –

+0

私は最初にコードを使用していますが、私のデータモデルではナビゲーションプロパティを定義する必要があります。これはドメインエンティティでは必要ありません。したがって、2つのモデルは同一ではありません。 –

+0

ここにはいくつかの戦略があります:vaughnvernon.co/?p=879 – jlvaquero

答えて

0

あなたの質問の下のあなたのコメントに基づいて、私が尋ねる最初の質問は、ドメインモデルでナビゲーションプロパティを使用したいのはなぜですか?ご覧のように、マッピングは複雑ですが、具体的な利点はどれですか?

また、hereを参照してください。「関連付けプロパティによるナビゲーションは、DDDの重要な概念です。」

ドメインモデルのナビゲーションプロパティ(CreatedByなど)を許可することで、ドメイン内のコアコンセプトにならないのはなぜですか?もちろん、遅延ロードを無効にし、明示的に要求された場合にのみナビゲーションプロパティをロードすることができます。

+0

タスクドメインエンティティはCreatedByリファレンスと決して対話しません。そしてそれはエンティティのこのタイプの多くのプロパティのうちの1つに過ぎません。私の主な目標は、本当に必要なものだけを使って、可能な限りドメインモデルをきれいにすることです。エンティティルートをロードするときに、これらの参照をロードすることは望ましくありません(レポートを生成する場合のみ)。私は、時にはそれがヌルになるという矛盾が気に入らず、時にはエンティティが理解する正確な理由なしにロードされることもあります。 –

+1

私は言ったように、ロードする必要はありませんが、必要に応じて明示的にロードされるだけです。 nullの参照は、なぜあなたのドメインを汚染するでしょうか? 「可能な限りクリーン」以外にも、他の議論や利点がありますか?私はあなたがここでは非常に純粋だと思うが、これは実際には問題ではないものを解決しようとすることによって、より多くの問題と複雑さをもたらすことが多い。とにかく、どのような解決方法があるのか​​教えてください:) –

+0

ドメインの清潔さを狂信的に感じるわけではありません。私はいくつかの妥協点を作る準備ができていますが、慎重に開始するのではなく、他の可能性を評価する。他には、永続性のためにEF Coreを使用したかったのですが、現在は値オブジェクトを非常にうまくサポートしていません。問題は、EF Coreを使用するかどうか、(私が避けたかった)レイヤー間のマッピング、またはNHibernateのようなものを使用するかどうかです。それらの決定.. :) –

関連する問題