すべてのエンティティにはレコードの作成者/変更者がスタンプされているため、Person エンティティをすべてのエンティティの集約ルートと見なすことができますか?
つまり、Person を参照するすべてのエンティティは、Person のコレクションになります。
public class Person
{
public virtual int PersonId { get; set; }
public virtual string Lastname { get; set; }
public virtual IList<OrderHeader> CreatedOrders { get; set; }
public virtual IList<OrderHeader> ModifiedOrders { get; set; }
// Other entities that have a reference on Person will be mapped as a collection under
// the Person entity
}
public class OrderHeader
{
public virtual int OrderId { get; set; }
public virtual DateTime OrderDate { get; set; }
public virtual Customer Customer { get; set; }
public virtual string CommentsOnThisOrder { get; set; }
// stamp audit-level concerns
public virtual Person CreatedBy { get; set; }
public virtual DateTime DateCreated { get; set; }
public virtual Person ModifiedBy { get; set; }
public virtual DateTime DateModified { get; set; }
public virtual IList<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public virtual OrderHeader OrderHeader { get; set; }
public virtual Product Product { get; set; }
public virtual int Quantity { get; set; }
public virtual decimal Price { get; set; }
}
これにより、基本的にすべてのエンティティが Person のコレクションになり、DDD 集計ルート規則に違反します。
DDD 集計に関する私の限られた理解では、OrderHeader を Person のコレクションにしてはなりません。Person を介して Order 集計を保存してはならないからです。Order 集計 (オブジェクト グラフ) を保存するための唯一の*entry*ポイントは、Person からではなく、OrderHeader から実行する必要があります。
これが私の本当の目標です
OrderHeader がコレクションとして Person にマップされていない場合、Person から OrderHeader への LEFT JOIN (.DefaultIfEmpty) を実行できない ORM *cough* NHibernate *cough* があります。Person から OrderHeader への LEFT JOIN を実現する唯一の方法は、OrderHeader をコレクションとして Person にマップすることです。
インフラストラクチャの問題 (たとえば、Linq の .DefaultIfEmpty を介して OrderHeader を Person へのコレクションにすることで Person から OrderHeader への LEFT JOIN を容易にすること) を許可する必要がありますか?
OrderHeader をコレクションとして Person にマップしない場合、NHibernate で Person から OrderHeader への LEFT JOIN (フラット化された結果、階層的ではないため、LEFT JOIN を使用する必要がある) を作成する必要がある場合、残された唯一のオプションはクエリオーバーを使用します。QueryOver は、Linq に比べて書くのが非常に面倒です。
Person から OrderHeader への LEFT JOIN を手動で (つまり、Linq の結合と .DefaultIfEmpty を介して) 行う場合、NHibernate の Linq で .DefaultIfEmpty(LEFT JOIN 機能) を使用できません。 NHibernate の Linq での LEFT JOIN は、コレクションと .DefaultIfEmpty を介して実行する必要があります。
ときどき(必要に応じて)行う場合、集約ルートのルールを破ることは実用的な選択ですか? たとえば、Linq を介して Person から OrderHeader への LEFT JOIN を容易にするために、OrderHeader をコレクションとして Person にマップする必要がありますか?
編集
サンプル Northwind データベース。注文のない顧客を含む、注文のあるすべての顧客を報告する必要がある場合 (例: PARIS)
CustomerID OrderID
OTTIK | 10407
OTTIK | 10684
OTTIK | 10554
PARIS |
PERIC | 10502
PERIC | 10474
PERIC | 10995
PERIC | 10354
PERIC | 11073
PERIC | 10322
、LEFT JOINを行う必要があります:
select c.CustomerID, o.OrderID
from customers c
left join orders o on c.CustomerID = o.CustomerID
order by c.CustomerID
これは、Linq の結合と .DefaultIfEmpty() で実行できます。ただし、NHibernate の Linq は、手動の Linq 結合の結果に対して .DefaultIfEmpty を実行できず、例外をスローします。NHibernate の DefaultIfEmpty は、コレクションにのみ適用できます。しかし、コレクションを集約ルートではないものにマッピングすることは、DDD 集約ルート規則に違反しているように感じます。また、すべてのテーブルに CreatedByPerson 参照があるため、Person (Customer は別の例です) などのすべてのエンティティには、すべてのエンティティのコレクションが含まれる可能性があります。
@ダニエルシリング:
また、OrderItem から OrderHeader を参照すると DDD に違反することに (良い意味で) 驚いています。それについて説明している何らかのホワイトペーパーまたは Martin Fowler の記事はありますか? 子エンティティから親エンティティを参照することはインフラストラクチャの問題とは見なされないため、DDD と見なされます。