我无法理解如何访问聚合根的子实体。从我的previous question的答案我现在明白我需要识别我的模型的聚合根,然后只设置处理这些根对象的存储库。
所以说我有一个包含Items的Order对象。项必须存在于Order和Order中,因此Order是聚合根。但是,如果我想在我的网站中包含OrderItem详细信息页面,该怎么办?此页面的URL可能类似于/ Order / ItemDetails / 1234,其中1234是OrderItem的ID。然而,这需要我直接通过ID检索项目,因为它不是聚合根,我不应该有一个OrderItemRepository,它可以通过ID来检索OrderItem。
因为我想使用独立于Orders的OrderItems,这意味着OrderItem实际上不是Order的聚合而是另一个聚合根?
答案 0 :(得分:1)
当然,我不了解您的业务规则,但我想不出您会订购没有订单的订单。并不是说你不想单独“与一个人合作”,但它仍然必须有一个订单,imo,并且订单是负责关系的;例如您可以通过添加或删除订单中的商品来表示所有这些。
在这种情况下,我通常仍然需要通过订单访问这些项目。它很容易设置,在URL中我会做/ order / 123 / item / 456。或者,如果项目排序存储/重要(通常至少间接地通过输入顺序存储),您可以执行/ order / 123 / item / 1来检索订单上的第一个项目。
然后,在控制器中,我只是从OrderRepository中检索订单,然后从那里访问相应的项目。
所有这一切,我确实同意Arnis,你并不总是必须遵循这种模式。这是一个逐案的事情,你应该在做之前评估权衡。
答案 1 :(得分:0)
在您的情况下,我会直接通过网址/OrderItem/1234
检索OrderItem。
我个人不尝试抽象持久性(我不使用存储库模式)。另外 - 我不遵循每个聚合根原则的存储库。但我确实将域模型与持久性隔离开来。
主要原因是 - 完全抽象持久性机制几乎是不可能的。这是一个漏洞抽象(例如,尝试为生活在污染存储库API下面的ORM指定eager / lazy加载)。
另一个原因 - 报告数据的方式并不重要。报告部分很无聊,相对不重要。应用程序的真正价值在于它可以做什么 - 流程自动化。因此,更重要的是您的应用程序的行为方式,如何保持一致,对象如何交互等等。
在考虑这个问题时,记住Law of Demeter是件好事。关键是 - 如果我们明确要隐藏内部,则应该仅应用 。在您的情况下 - 我们不想隐藏订单商品。
所以 - 利用我们知道实体ID是全局唯一的事实(而不是仅仅在Order上下文中是唯一的)它只是一个捷径,直接检索它们没有任何问题。
有趣的是 - 这可以推进 甚至行为封装也可以和should be loosened up too。
E.g。 - 让orderItem.EditComments("asdf")
比order.EditOrderItemComments(order.OrderItems[0], "asdf")
更有意义。