Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 人是聚合根吗? 因为所有实体都有谁创建/修改记录的标记,我们能把一个人实体看作是所有实体的聚合根吗?< /P>_C#_Linq_Nhibernate_Domain Driven Design_Aggregate - Fatal编程技术网

C# 人是聚合根吗? 因为所有实体都有谁创建/修改记录的标记,我们能把一个人实体看作是所有实体的聚合根吗?< /P>

C# 人是聚合根吗? 因为所有实体都有谁创建/修改记录的标记,我们能把一个人实体看作是所有实体的聚合根吗?< /P>,c#,linq,nhibernate,domain-driven-design,aggregate,C#,Linq,Nhibernate,Domain Driven Design,Aggregate,也就是说,所有引用此人的实体都将成为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<Or

也就是说,所有引用此人的实体都将成为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; }
}
,我们需要执行左联接:

select c.CustomerID, o.OrderID
from customers c
left join orders o on c.CustomerID = o.CustomerID
order by c.CustomerID
这可以通过Linq的join和.DefaultIfEmpty()实现。然而,NHibernate的Linq不能对手动Linq连接的结果执行.DefaultIfEmpty,它会抛出一个异常。NHibernate的DefaultIfEmpty只能应用于集合。但我觉得将集合映射到非聚合根的对象违反了DDD聚合根规则。同时,所有实体,如Person(Customer是另一个示例),都可能包含所有实体的集合,因为每个表都有一个CreatedByPerson引用

@丹尼尔斯:

我也很惊讶(以一种好的方式),从OrderItem引用OrderHeader违反了DDD。我们是否有白皮书或马丁·福勒的文章对此进行了阐述?我认为从子实体引用父实体不被视为基础设施问题,因此被视为DDD。

关于DDD决策的思考。。。 听起来您希望能够做到这一点:

var people = session.Query<Person>()
    .FetchMany(x => x.CreatedOrders)
    .Where(x => x.Id == personId);
一般来说,如果你发现你违反了DDD原则,这通常是一个很好的指标,表明你做错了什么,你通常不必寻找太远的其他支持证据

不过,每隔一段时间,你确实需要稍微改变一下规则,我认为这是可以接受的。例如,我通常尝试只映射每种关系的一面——从DDD的角度来看,这就是我真正需要的。当引用其他聚合根时,这通常意味着只对
多对一
侧进行建模,对于聚合根中的引用(从根到其子级),这通常意味着只对
一对多
进行建模,并将
多对一
保留在模型之外。这意味着将
OrderItem.OrderHeader
排除在模型之外

如果您需要了解特定产品的销售量,但仅限于已提交的订单,该怎么办?最简单的方法是:

var quantitySold = session.Query<OrderItem>()
    .Where(x => x.Product.Id == productId && x.OrderHeader.Submitted)
    .Sum(x => x.Quantity);
。。。还有一个是为了得到没有命令的人:

var peopleWithNoOrders = session.Query<Person>()
    .Where(p => !session.Query<OrderHeader>().Any(o => o.CreatedBy == p));
var peopleWithNoOrders=session.Query()
.Where(p=>!session.Query().Any(o=>o.CreatedBy==p));

您的
人员
可能是一个集合,而您的
订单
可能是一个集合。一个聚合根实例不应引用另一个的实例。尽量不要从ORM或数据库的角度来考虑

我可以向您指出这些答案(它们可能相关):


您在编辑中向我提到,您的目标是将一些数据导出到Excel电子表格或CSV文件中。您可以添加一个简短的输出示例吗?@DanielSchilling这是我引用的唯一一个示例,说明了通过手动执行左连接(即通过Linq的连接和.DefaultIfEmpty:-)导出到电子表格或CSV并不是执行手动连接的唯一用例。DefaultIfEmpty()是,但是一个特定的用例是做任何事情的唯一原因。如果没有明确的“为什么要这样做”,你就不可能知道“你应该做什么”。如果没有“为什么”-或者如果原因太模糊,答案是“不要这样做”。@Daniels我给出的关于我的问题的示例已经是一个特定的用例。无法使用上面的用例翻转左连接构造,必须从CustomerID开始,然后向下到OrderHeader。我可以对客户执行纯DDD的唯一方法,即不让客户成为聚合的根,而能够生成像我上面编辑的那样的报告,就是使用NHibernate的QueryOver:-)我想我只是想有一个确认偏见,如果可以违反DDD(使OrderHeader成为客户的集合)只是为了方便地在NHibernate的Linq上执行左连接机制。与Linq相比,QueryOver的左连接机制过于复杂,不必要地复杂。NHibernate的QueryOver可以手动进行左连接,也就是说,即使没有映射集合,但它的方法太可怕、太乏味了,我还不准备接受NHibernate的QueryOver,只是为了正确地坚持DDD:-)@Hao,回应您的“我也很惊讶(以一种好的方式)”,表示从OrderItem引用OrderHeader违反了DDD”。埃里克·埃文斯实际上是DDD方面的权威(如果有权威的话)——而我实际上还没有读过他的书。它在我的待办事项清单上。我之所以说,从DDD的角度来看,只对关系的一方进行建模更好,是因为它完全清楚了哪个实体负责关系。不存在歧义的可能性。如果你将关系的双方都映射到一起,那么
多对一
方,即孩子对父母的引用,实际上成为负责人。在可能的情况下,只映射一个方面,可以更准确地表示关系。通常你也会发现这是你所需要的。它还迫使您识别聚合根并将其视为聚合根,因为对于每种关系,您必须决定“我应该将多对一还是一对多映射?”——这个选择主要取决于哪些事物是聚合根。我在回答中添加了关于问题左外连接部分的内容。见上文。
var orders = session.Query<OrderHeader>()
    .Fetch(x => x.CreatedBy)
    .Where(x => x.CreatedBy.Id == personId)
    .Where(x => x.OrderDate >= DateTime.Now.AddYears(-1))
    .Skip(100)
    .Take(50);
var quantitySold = session.Query<OrderItem>()
    .Where(x => x.Product.Id == productId && x.OrderHeader.Submitted)
    .Sum(x => x.Quantity);
var orders = session.Query<OrderHeader>()
    .Fetch(x => x.CreatedBy);
var peopleWithNoOrders = session.Query<Person>()
    .Where(p => !session.Query<OrderHeader>().Any(o => o.CreatedBy == p));