7

私は、この DDD\LinqToSql ビジネス全体について少し混乱しているようです。POCOS と linq to sql を使用してシステムを構築しており、集約ルートのリポジトリがあります。たとえば、クラス Order->OrderLine がある場合、Order のリポジトリがありますが、OrderLine は集約のルートであるため、OrderLine はありません。リポジトリには Order を削除するための delete メソッドがありますが、OrderLine を削除するにはどうすればよいでしょうか? OrderLines コレクションから行を削除する RemoveOrderLine という Order のメソッドがあると思われるかもしれませんが、基になる l2s テーブルから OrderLine を削除する必要もあります。OrderLine のリポジトリはありませんが、どうすればよいですか?

おそらく、ドメインオブジェクトが実際に集約内のものを削除するために使用するルートと内部汎用リポジトリを照会するための専用の公開リポジトリがありますか?

public class OrderRepository : Repository<Order> {
    public Order GetOrderByWhatever();
}

public class Order {
    public List<OrderLines> Lines {get; set;} //Will return a readonly list
    public RemoveLine(OrderLine line) {
        Lines.Remove(line);
        //************* NOW WHAT? *************//
        //(new Repository<OrderLine>(uow)).Delete(line) Perhaps??
        // But now we have to pass in the UOW and object is not persistent ignorant. AAGH!
    }
}

これに苦しんでいるのは私だけではないので、他の人が何をしたか知りたいです.... 願っています.... ありがとう

4

4 に答える 4

2

関連するロジックを呼び出す Order で RemoveOrderLine を呼び出します。これには、永続化されたバージョンの変更は含まれません。

後で、変更された注文を受け取るリポジトリで Save/Update メソッドを呼び出します。特定の課題は、ドメインオブジェクトで何が変更されたかを知ることであり、いくつかのオプションがあります (私がリストしたものよりも多くのオプションがあると確信しています):

  • ドメイン オブジェクトに変更を追跡させます。これには、注文明細行から x を削除する必要があることを追跡することが含まれます。エンティティの追跡に似たものも除外される可能性があります。
  • 永続化されたバージョンをロードします。永続化されたバージョンとメモリ内バージョンの違いを認識するコードをリポジトリに配置し、変更を実行します。
  • 永続化されたバージョンをロードします。ルート集約にコードを用意して、元のルート集約との違いを取得します。
于 2009-03-17T01:46:53.380 に答える
1

この正確な問題に苦労した後、私は解決策を見つけました。デザイナーがl2slで何を生成するかを見た後、解決策は注文と注文ラインの間の双方向の関連付けにあることに気付きました。オーダーには多くのオーダーラインがあり、オーダーラインには単一のオーダーがあります。解決策は、双方向の関連付けとDeleteOnNullと呼ばれるマッピング属性を使用することです(完全な情報をグーグルで検索できます)。私が見逃していた最後のことは、エンティティクラスがl2sエンティティセットからの追加イベントと削除イベントに登録する必要があるということでした。これらのハンドラーでは、注文明細の注文の関連付けをnullに設定する必要があります。l2sデザイナーが生成するコードを見ると、この例を見ることができます。

これは苛立たしいことですが、何日も苦労した後、私はそれを機能させました。

于 2009-11-04T23:10:27.570 に答える
1

最初に、インターフェースを公開して、集約ルート (すなわち Order()) への参照を取得する必要があります。Factory パターンを使用して、Aggregate Root (つまり Order()) の新しいインスタンスを新しく作成します。

そうは言っても、集約ルートのメソッドは、それ自体ではなく、関連するオブジェクトへのアクセスを制御します。また、複合型を集約ルート (つまり、例で述べた Lines() IList コレクション) で public として公開しないでください。これは、Order.Lines.Add() などのメソッドに「ドット ウォーク」することはできないという減分率 (sp ck) の法則に違反しています。

また、クライアントが集約ルート上の内部オブジェクトへの参照にアクセスすることを許可する規則にも違反しています。集約ルートは、内部オブジェクトの参照を返すことができます。限り、外部クライアントはそのオブジェクトへの参照を保持できません。つまり、RemoveLine() に渡す「OrderLine」です。外部クライアントがモデルの内部状態 (つまり、Order() とその OrderLines()) を制御できるようにすることはできません。したがって、OrderLine はそれに応じて動作する新しいインスタンスであると想定する必要があります。

public interface IOrderRepository
{
  Order GetOrderByWhatever();
}

internal interface IOrderLineRepository
{
  OrderLines GetOrderLines();
  void RemoveOrderLine(OrderLine line);
}

public class Order
{
  private IOrderRepository orderRepository;
  private IOrderLineRepository orderLineRepository;
  internal Order()
  {
    // constructors should be not be exposed in your model.
    // Use the Factory method to construct your complex Aggregate
    // Roots.  And/or use a container factory, like Castle Windsor
    orderRepository = 
            ComponentFactory.GetInstanceOf<IOrderRepository>();
    orderLineRepository = 
            ComponentFactory.GetInstanceOf<IOrderLineRepository>();
  }
  // you are allowed to expose this Lines property within your domain.
  internal IList<OrderLines> Lines { get; set; }  
  public RemoveOrderLine(OrderLine line)
  {
    if (this.Lines.Exists(line))
    {
      orderLineRepository.RemoveOrderLine(line);
    }
  }
}

Order() の新しいインスタンスを作成するためのファクトリを忘れないでください。

public class OrderFactory
{
  public Order CreateComponent(Type type)
  {
    // Create your new Order.Lines() here, if need be.
    // Then, create an instance of your Order() type.
  }
}

外部クライアントには、インターフェイスを介して IOrderLinesRepository に直接アクセスし、集約ルート内の値オブジェクトの参照を取得する権利があります。しかし、集約ルートのメソッドからすべての参照を強制することで、それをブロックしようとしています。したがって、上記の IOrderLineRepository を内部としてマークして、公開されないようにすることができます。

私は実際に、すべての Aggregate Root 作成物を複数の Factory にグループ化しています。「一部の集約ルートには複合型のファクトリがあり、他にはありません」というアプローチは好きではありませんでした。ドメイン モデリング全体で同じロジックに従う方がはるかに簡単です。「ああ、Sales() は Order() のような集約ルートです。それにもファクトリが必要です。」

最後に、SalesOrder() のように、Sales() と Order() の 2 つのモデルを使用する組み合わせがある場合、Service を使用して、SalesOrder() のインスタンスを作成し、Sales()または Order() Aggregate ルートも、そのリポジトリまたはファクトリも、SalesOrder() エンティティを制御します。

Abel Avram と Floyd Marinescu による Domain Drive Design (DDD) に関するこの無料の本は、100 ページの大きな活字であなたの質問に直接答えてくれるので、強くお勧めします。ドメインエンティティをモジュールなどにさらに分離する方法とともに。

編集:コードを追加

于 2009-03-17T02:09:54.777 に答える
0

フォローアップとして....私は(SQLへのリンクではなく)nhibernateの使用に切り替えましたが、実際にはOrderLineのリポジトリは必要ありません。Order のコレクションから OrderLine を削除すると、データベースから OrderLine が削除されます (マッピングが正しく行われていると仮定します)。私はメモリ内リポジトリと交換しているので、(注文の親を知らずに) 特定の注文明細を検索したい場合は、注文を orderline にリンクする linq to nhibernate クエリを記述できます。ここで、orderlineid = 値です。そうすれば、データベースとメモリ内からクエリを実行するときに機能します。では、どうぞ...

于 2009-04-14T21:39:07.993 に答える