首页 / 软件开发 / .NET编程技术 / EntityFramework之领域驱动设计实践(七):模型对象的生命周期 - 仓储
EntityFramework之领域驱动设计实践(七):模型对象的生命周期 - 仓储2012-02-09 博客园 dax.net上文中已经提到了管理领域模型对象生命周期的两大角色,即工厂与仓储,并对工厂的EntityFramework实践作了详细的描述。本节主要介绍仓储的概念,由于仓储的内容比较多,我将在接下来的两节中具体讲解仓储的架构设计与实践经验。仓储(Repository),顾名思义,就是一个仓库,这个仓库保存着领域模型的实体对象。在业务处理的过程中,我们有可能需要把正在参与处理过程的对象保存到仓储中,也有可能会从仓储中读取需要的实体对象,抑或将对象直接从仓储中删除。上文也用一张简要的状态图描述了仓储在管理领域模型对象生命周期中所处的位置。与工厂相同,仓储的关注对象也应该是聚合根,而不是聚合中的某个实体,更不应该是值对象。或许你会说,我当然可以针对销售订单行(Order Line)进行增删改查等操作,而无需跟销售订单(Sales Order)打交道。当然,你的确可以这样做,但如果你一定要坚持自己的观点,那么你就是把销售订单行(Order Line)当成是聚合根了,也就是说,你默许Order Line在你的领域模型中,是一种具有独立概念的实体。关于这个问题,在领域驱动设计的社区中,有人发表了更为“强势”的观点:One interesting DDD rule is: you should create repositories only for aggregate roots.
When I read about it the first time I interpreted it this way: create repositories at least for all aggregate roots, but when you need a little repository for something else go ahead and implement it (and nobody will know what you did).
So I was thinking that the rule is somehow flexible. It turns out that it"s not, and this is good: it keeps the domain stable and coherent. If entity A is an aggregate root, entity B is part of that aggregate, and you need to load B separated from the concept of A, this is a sign that the implementation does not reflect the business needs (anymore). In this case, B should probably become the root of its own aggregate意思是说,如果实体A是聚合根,而B是该聚合中的一个实体,而你的设计希望绕过A而直接从仓储中获得B,那么,这就是一个信号,预示着你的设计可能存在问题,也就是说,B很有可能被当成是另一个聚合的根,而这个聚合只有一个对象,就是B本身。由此看来,聚合的划分与仓储的设计,在领域驱动设计的实践中是非常重要的内容。工厂是从无到有地创建对象,从代码上看,工厂里充斥着new关键字,用以创建对象,当然,工厂的职责并不完全是new出一个对象那么简单。而仓储则更偏向于对象的保存和获得,在获得的时候,同样也会有新的对象产生,这个新的对象与保存进去的对象相比,引用不同了,但数据和业务ID值(也就是我们常说的实体键)是不变的,因此,在领域层看来,从仓储中读取得到的对象与当时保存进去的对象并没有什么两样。