我是DDD的新手,所以请耐心等待。
情景 聚合A和 聚合B
A通过关系ID与B相关,它位于聚合B上(因此它将是B.A_Id 现在,我必须创建B,但是如果B.SalesDate距离A.ReleaseDate超过7个日历日,我就无法创建B.我的问题是关于Aggregate B的CommandHandler,我可以对Aggregate A进行查询以获取A.ReleaseDate,这样我就可以检查提供的B.SalesDate是否不超过7个日历日吗?这是在Aggregate B上使用CommandHandler的代码的一部分:
public async Task Handle(AddBCommand command, CancellationToken cancellationToken)
{
if (!command.IsValid())
{
NotifyValidationErrors(command);
return;
}
// this is where I do a query on Aggregate A to get details using the Id (which is A.Id from Aggregate A) selected on UI
var aggregateADetails = await A_Repository.GetFirstAsync(x => x.Id == command.Id);
//if (isCloserthan7Days.)
//{
// NotifyError(string.Empty, "B.SalesDate is 7 days closer than A.ReleaseDate");
// return;
//}
所以在这个CommandHandler上,我实例化了2个存储库,1个用于B,1个用于A用于查询。这样做会违反DDD规则吗?对不起,不太清楚。
谢谢
答案 0 :(得分:0)
您的命令处理程序被视为应用程序层,而不是域层。
考虑到上述情况,从命令处理程序加载聚合A并将数据推送到聚合B是完全正常的,但逻辑必须在域层中实现,这意味着聚合B方法。一般来说,应用层的作用(如果您考虑它)是检索域层方法执行其工作所需的所有数据。所需数据(在这种情况下)来自另一个聚合是无关紧要的。在语义上它就像你从该聚合的读模型投影中读取一个属性一样,它与DDD的“规则”相关(尽管如果你考虑从异步生成的投影读取,你应该知道引入最终一致性问题的可能性)。要记住的重要一点是,即使您可以从聚合A中读取,但在此更改的范围内,您应该只编辑(并保存)一个聚合。
我在原来的答案中没有提到的东西,但应该有,康斯坦丁在评论中指出的是一致性问题。从查询存储中读取(如上所述)可能会引入最终的一致性问题,从另一个聚合中读取数据也可能会引入一致性问题,因为您正在读取聚合A中的数据,这些数据可能在聚合B完成操作并尝试得到坚持。
(回复编辑):在您的代码示例中,您的方法是应用程序层和域层逻辑的组合。从repos加载是应用层,但是决定是否应该在聚合中执行的逻辑应该属于聚合。我可能在这里遗漏了一些信息,但从我现在看到的很少,我猜你可能有一个动态域模型。无论如何,我的初步回应仍然适用。