Rob*_*ode 7 c# repository-pattern
我已经看过一些文章说明存储库应该只返回方法调用的完整域模型,例如GetAll().但是,如果我需要的是一个列表,其中每个项目仅由具有30个属性的域模型中的2个属性组成?我想显示列表部门,其中列表仅显示部门名称和位置.用户可以从该列表中选择一个部门并请求其详细信息.从那里我可以进行另一个存储库调用,以返回所选内容的完整域模型,并允许进行典型的crud操作.
但是,如果我不应该使用存储库来返回完整域模型的子集,那么建议的方法是什么?我想我可以返回一个完整的域模型列表,但这似乎是浪费网络带宽,以便通过网络带来如此多的数据,我将不会使用.如果我创建另一个模型来表示感兴趣的2个属性,这似乎是另一个大量的工作要做,因为我拥有的每个模型都有自己的存储库和存储库访问的服务模块.
从存储库中检索完整域模型子集的建议方法是什么?此外,我不知道如果我违反仅拉动完整模型的规则也会发生什么,也会拉动部分模型数据,这只会用于选择列表.
在我看来,这可以被认为是一个非常主观的问题....我的建议是基于DDD实践.
在上下文中DDD,存储库应始终返回域对象(即,a Aggregate).聚合是数据存储传输的基本元素 - 您请求加载或保存整个聚合. 由应用程序层决定将数据转换DTO为对视图有意义的模型.
为了解决您的问题:
您描述的选择列表示例是DTO的理想选择.如果创建DTO以表示支持视图的两个属性,则表示您正在创建POCO对象.这个对象重量轻,创建起来很便宜.您可以使用AutoMapper等工具来协助DTO和域模型之间的映射.在更改视图时,您的更改通常与DTO对象及其映射隔离.您尚未通过应用程序层将视图概念泄露到域层.
DTO将减少请求客户的带宽成本(即,您没有返回具有30个属性的域实体并公开显示您的实体)
您可以使用单个存储库来支持Department实体的部门选项列表视图和CRUD操作.
使用一个域模型.但是,创建需要支持该域模型或模型的视图的DTO.
在一天结束时,DDD并不便宜,它不是一颗银弹.
如果你有一个简单的问题要解决,那么使用简单的CRUD和一个对你有意义的模型.这些只是指导方针......
DDD对于开发极高基本复杂度的软件(具有许多相关业务规则)是有意义的.和/或具有明确未来的软件,其中域模型可以比基础架构更长久,或者业务需求快速变化.在其他情况下,DDD可能带来比解决更多的意外复杂性.
对于它的价值,这里有一些关于DDD概念的额外评论,希望有助于:
用例最佳存储库查询:
Vaughn Vernon将模式描述Use Case optimal Repository Queries为......而不是读取各种类型的多个整个聚合实例,然后以编程方式将它们组合成单个容器(DTO or DPO),您可能希望使用所谓的用例最优查询.在这里,您可以使用查找器查询方法设计存储库,该方法将自定义对象组合为一个或多个Aggregate实例的超集.该查询动态地将结果放入Value Object(DDD)特定设计中以满足用例的需要.
您设计的是值对象而不是DTO,因为查询是特定于域的,而不是特定于应用程序(如DTOS).然后,视图呈现直接使用自定义用例最佳值对象.
这是一种类似的使用方法CQRS; 但是,存储库正在执行统一域模型存储,而不是旨在支持只读视图的数据库.
沃恩弗农还说:
如果您发现必须创建许多finder方法来支持多个存储库上的用例最优查询,那么它可能是代码味道.
这可能是因为您错误判断了Aggregate边界并忽略了设计一个或多个不同类型的Aggregates的机会.
Vaughn将此代码的气味描述为:存储库掩码聚合错误设计
这也可能表明需要考虑使用CQRS.
DDD查询模型(又称读取模型)
查询模型是非规范化数据模型.它仅用于显示数据,而不是用于提供域行为.Vaughn Vernon说:
如果这种数据模型是SQL数据库,则每个表都将保存单一类型的客户端视图(显示)的数据.该表可以包含许多列,甚至是任何给定用户界面显示视图所需的列的子集.可以从表创建表视图,每个表都用作整体的逻辑子集.
他还声明可以根据需要为许多观点提供支持.值得注意的是,CQRS基于视图可以既便宜又一次性(用于开发和维护).使用Event Sourcing,使用这种方法很好.
DDD DTO:
一种方法是让应用程序层组装DTOs.该DTO会是一个投影域实体或实体的一个子集,以满足您的观点.
Vaughn Vernon简单地说 -
DTO旨在保存需要在视图中显示的全部属性
DDD存储库
Martin Fowler将Repository模式描述为:
使用类似集合的接口访问域对象,在域和数据映射层之间进行调解.
请参考以下SO问题: