获取所有聚合根实体子实体?
我正在尝试将我的应用程序从每个实体的存储库重构为每个聚合根的存储库。
一个基本的例子是我有一个 Cars 实体根。汽车有租赁合同。据我所知,没有汽车就没有合同,因此汽车是总根。
我正在尝试实现一个用户视图,它将显示系统中的每个合同(根实体的所有子实体)。在重构之前,我可以转到我的合同存储库并获取全部。由于合同存储库已被删除(因为它不是根),我现在需要将所有汽车从我的存储库中取出,然后获取它们的所有合同。
的接口
public interface ICarRepository
{
IQueryable<Car> All { get; }
IQueryable<Car> AllIncluding(params Expression<Func<Car, object>>[] includeProperties);
Car Find(long id);
void InsertOrUpdate(Car car);
void Delete(long id);
void Save();
}
我的存储库具有我想要创建 ICarManagementService 并使其具有 GetAllContracts 方法(可能带有过滤器参数) 。这是否意味着要获取我需要的所有合同,将所有汽车实体及其合同取出,然后检索每个实体关联的租赁合同并过滤它们?
然后我可以将这些传递给控制器并像以前一样自动映射合约。
这是最佳实践吗?
谢谢格雷姆
I am attempting to refactor my application from a repository per entity to a repository per aggregate root.
A basic example would be I have an entity root of Cars. Cars have hire contracts. As far as I can see contracts don't exist without cars hence cars is the aggregate root.
I am trying to implement a user view which will shows every contract in the system(all the child entities of the root entities). Before refactoring I could just go to my contracts repository and get All. As contracts repository has been removed (as its not a root) I now need to get all cars out of my repository and then get all their contracts.
My repository has the interface
public interface ICarRepository
{
IQueryable<Car> All { get; }
IQueryable<Car> AllIncluding(params Expression<Func<Car, object>>[] includeProperties);
Car Find(long id);
void InsertOrUpdate(Car car);
void Delete(long id);
void Save();
}
I thought of creating an ICarManagementService and having it have a GetAllContracts method (perhaps with filter parameters). Would that mean to get all contracts I need to pull all car entities out with their contracts and then retrieve each entities associated hire contracts and filter them?
I can then pass these to the controller and AutoMap the contracts as before.
Is this best practice?
Thanks
Graeme
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这不一定是真的。 “没有则不存在”不足以使实体成为聚合根的一部分。考虑经典的订单处理领域。您有一个作为聚合根的订单。您还有一个作为聚合根的客户。订单不能没有客户而存在,但这并不意味着订单是客户聚合的一部分。在 DDD 中,一个聚合内的实体可以引用其他聚合根。来自 DDD 书籍:
聚合是生命周期和数据交换的单位。它本质上是一组强制执行不变量的对象。如果您有多个用户同时更改域,则您需要锁定此内容。
回到你的问题,我的理解是该域名类似于租赁/租赁汽车/卡车/豪华轿车/推土机。我认为 HireContract 可能不是 Car 聚合的一部分,因为它们可能有不同的生命周期,而 HireContract 本身就有意义,没有汽车。它似乎更像是订单-产品关系,也是两个不同聚合相互引用的经典示例。这一理论也被业务需要看到“所有合约”的事实所证实。他们可能不认为 Car 包含所有合同。如果这是真的,那么您需要保留您的 ContractsRepository。
在不相关的说明中,您可能有兴趣阅读有关存储库接口的答案设计。
This is not necessarily true. 'Don't exist without' is not enough for an entity to become a part of an Aggregate Root. Consider classic order processing domain. You have an Order that is an Aggregate Root. You also have a Customer that is an Aggregate Root. Order can not exist without a Customer but it does not mean that Orders are part of the Customer Aggregate. In DDD entities inside one Aggregate can have references to other Aggregate Roots. From DDD book:
Aggregate is a life cycle and data exchange unit. It is essentially a cluster of objects that enforces invariants. This is something you want to be locked if you have multiple users changing domain at the same time.
Back to your question, my understanding is that the domain is something like rent / lease a car / truck / limo / bulldozer. I think that HireContract may not be a part of Car aggregate because they may have different lifecycles and HireContract just makes sense on its own, without a Car. It seem to be more of a Order-Product relationship that is also a classic example of two different Aggregates referencing each other. This theory is also confirmed by the fact that business needs to see "All Contracts". They probably don't think of Car containing all Contracts. If this is true than you need to keep your ContractsRepository.
On an unrelated note, you might be interested in reading this answer about repository interface design.
将读/查询的概念与写/命令分开,按照 CQRS 的指导,最好通过分离由只读查询组成的读模型和由执行某些逻辑的命令组成的写模型来设计应用程序在域模型上。
因此,查询所有聚合根或创建自定义查询来连接数据集并不是域存储库的良好候选者,而是将这些查询放入读取存储库(或更好的命名为Finders)中。
如果您发现自己想要查询对象集合以执行某些域逻辑,那么这表明您必须抽象该集合并将其放入聚合根中以封装它们并使业务操作或方法对它们起作用。
查看(http://moh-abed.com/2011/09/13/pure-old-ddd-with-a-twist-from-cqrs/)和(http://simon-says-architecture.com/ 2011/08/23/存储库)
Separate the concept of read/query from the write/command, as guided by CQRS it is preferable to design the application by separating read model which consists of read only queries and the write model on the other hand which consists of commands to execute certain logic on the domain model.
thus querying all aggregate roots or creating custom queries to join sets of data is not a good candidate of domain repository, instead put these queries into read repository (or better named Finders).
if you find yourself wanting to query a collection of objects in order to execute some domain logic then it is an indicator that you have to abstract this collection and put it into an aggregate root to encapsulate them and make the business operation or method act on them.
check out (http://moh-abed.com/2011/09/13/pure-old-ddd-with-a-twist-from-cqrs/) and (http://simon-says-architecture.com/2011/08/23/repository)