EaBIM一直以来积极响应国家“十二五”推进建筑业信息化的号召,对建筑领域的信息技术开展深入技术交流和探讨!致力于打造“BIM-建筑师-生态技术”三位一体综合资源交流共享平台,希望为BIM与可持续设计理念及技术的普及做出微小的贡献!!!

EaBIM

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
查看: 472|回复: 0
打印 上一主题 下一主题

[面向对象] 实体框架之领域驱动实践(七):模型对象的生命周期 - 仓储

[复制链接]

1514

主题

7465

帖子

1万

积分

admin

Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10

积分
12404

社区QQ达人

跳转到指定楼层
楼主
发表于 2014-1-10 11:01:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
上文中已经提到了管理领域模型对象生命周期的两大角色,即工厂与仓储,并对工厂的Entity Framework实践作了详细的描述。本节主要介绍仓储的概念,由于仓储的内容比较多,我将在接下来的两节中具体讲解仓储的架构设计与实践经验。
  仓储(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值(也就是我们常说的实体键)是不变的,因此,在领域层看来,从仓储中读取得到的对象与当时保存进去的对象并没有什么两样。
  你可能已经体会到,仓储就是一个数据库,它与数据库一样,有读取、保存、查询、删除的操作。我只能说,你已经了解到仓储的职能,并没有了解到它的角色。仓储是领域层与基础结构层的一个衔接组件,领域层通过仓储访问外部存储机制,这样就使得领域层无需关心任何技术架构上的实现细节。因此,仓储这个角色的职责不仅仅是读取、保存、查询、删除,它还解耦了领域层与基础结构层。在实践中,可以使用依赖注入的方式,将仓储实例注入到领域层,从而获得灵活的体系结构。
下面是我们案例中,仓储接口的代码:

                               
登录/注册后可看大图
  IRepository是一个泛型委托接口,泛型类型被where子句限定为Entity Framework中的EntityObject,与此同时,where子句还限定了泛型类型必须实现IAggregateRoot接口。换句话讲,IRepository接口的泛型类型必须是继承于EntityObject类,并实现了IAggregateRoot接口的引用类型。根据我们在“聚合”一文中的表述,我们可以实现针对Customer、Order以及Category实体类的仓储类。
  这里只给出了仓储实现的一个引子,至少到目前为止我们已经简单地定义了仓储实现的一个框架,也就是上面这个IRepository泛型接口。接口中具体要包括哪些方法,不是本系列文章要讨论的关键问题。为了描述与演示,我们只为IRepository接口设计如上四个方法,即Add、GetByKey、Remove和Update。接下来,我将详细描述在基于实体框架(Entity Framework)的仓储设计中所遇到的困难,以及如何在实践中解决这些困难。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 转播转播 分享分享 分享淘帖 支持支持 反对反对
工作时间:工作日的9:00-12:00/13:30-18:00,节假日不在线,请勿留言
*滑块验证:
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|EaBIM网 ( 苏ICP备2020058923号-1  苏公网安备32011502011255号

GMT+8, 2024-11-16 12:31

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表