Domain driven design 存储库实现是我的域的一部分吗?存储库应该有SQL查询吗?

Domain driven design 存储库实现是我的域的一部分吗?存储库应该有SQL查询吗?,domain-driven-design,Domain Driven Design,存储库实现是我的域模型的一部分,还是我应该只将它们抽象为我的域的一部分 我应该将SQL查询放在我的存储库中,还是将它们放在另一种模式中,并作为存储库的依赖项传递 谢谢 更新 更新2 请看一看:如果您使用的是hexagon、onion或ports and adapters样式的体系结构,那么通常的做法是将存储库接口放在域模型中,将存储库实现放在持久层/适配器中。然后使用IoC容器将它们连接起来,并将持久层中的引用添加到域模型中。这允许您在持久层中使用域模型实体和值对象,但也可以通过IoC访问域模

存储库实现是我的域模型的一部分,还是我应该只将它们抽象为我的域的一部分

我应该将SQL查询放在我的存储库中,还是将它们放在另一种模式中,并作为存储库的依赖项传递

谢谢

更新

更新2
请看一看:

如果您使用的是hexagon、onion或ports and adapters样式的体系结构,那么通常的做法是将存储库接口放在域模型中,将存储库实现放在持久层/适配器中。然后使用IoC容器将它们连接起来,并将持久层中的引用添加到域模型中。这允许您在持久层中使用域模型实体和值对象,但也可以通过IoC访问域模型中的存储库

SQL的存放位置由您决定,这不是DDD的问题,但它可能属于您的存储库。标准实践是使用类似ORM的实体框架或NHibernate使用存储过程或LINQ样式的查询。在后一种情况下,查询将存在于存储库中

好的做法是存储库接受域实体(即用于创建/更新)并返回域实体(即用于查询)。ORM生成的任何自动生成的实体通常都会被存储库隐藏。这可能会消除从ORM中获得的许多“好处”(如延迟加载和双向导航属性),但这些东西通常会阻碍良好的DDD,尤其是良好的对象/实体设计

额外细节

存储库模式的目标是“像列表一样”隐藏持久性细节。因此,设计存储库的目标是使其成为一个简单的集合,在其中可以添加、删除和更改项目。在幕后,您的存储库可以(应该)知道它存储数据的位置,即SQL数据库、平面文件、XML文件等


在DDD中,理想情况下,每个聚合根需要一个存储库。例如,持久化单个
客户
聚合根(聚合根可能是单个实体,或者是由其他实体或值对象组成的实体)可能会导致写入4个单独的表。

是的,存储库实现肯定是域模型的一部分。例如,在域驱动设计中,实现存储库时的主要目标是关注使用存储库的代码的透视图,而不是存储库中的代码本身

在第155页:

实现存储库

根据所采用的技术,实现将有很大的不同 用于持久性和您拥有的基础架构。理想是 向客户机隐藏所有内部工作(尽管不是从 客户端的开发人员),以便客户端代码将是相同的 数据存储在对象数据库中,存储在关系数据库中 数据库,或者干脆保存在内存中

此外,可以将SQL查询放入存储库实现中。在分层体系结构中,域层依赖于基础结构层,SQL是基础结构层的一部分。但是,当您需要事务时,使用该模式几乎是不可能的,因为存储库实现不应该负责管理事务,而事务通常应该在服务层中实现


如果您需要域模型中的事务,则很可能需要为存储库使用ORM或特定于域的查询语言,这样,您就可以在基础结构层对象中编写SQL查询,该对象将跟踪哪些对象需要在事务的开始和结束时被持久化。

我的存储库知道我的数据库架构是件坏事吗?因为如果我使用不同的模式实现另一个数据库,例如,我知道
用户
表的存储库现在无法处理
tbl_用户
。如何避免这种情况,每个数据库模式一个存储库实现?请看一看:我还想提到,“数据库可能会改变”是一件不太可能改变的事情,不应该花费很多精力来预测这一点。事实上,许多遗留应用程序在其遗留数据库上运行,直到最终退役。另外,如果您确实更改了数据库,则进行更改不会违反OCP。您所需要做的就是创建新的存储库,并使用IoC容器中的设置进行切换。只有抽象是域的一部分。您应该能够在不中断域的情况下交换实现。存储库实现可以包含原始SQL,也可以依赖于ORM,不管是什么@杰夫克莱斯,你怎么看?从您发布的图表来看,似乎应该有一个接口
UserRepository
和两个具体的类来实现它:
schemauserrepository
SchemaBUserRepository
。然后使用控制反转,您可以将适当的存储库注入工厂。@EdSaito那是很早的事,但想象一下这样一个场景:您只有两个架构,而且您将有不同的数据访问层实现(ORM引擎),每个实体将有4个存储库!!!SchemaEngineAUserRepository,SchemaBEngineAUserRepository,SchemaEngineBUserRepository,SchemaBEngineAUserRepository!这听起来很奇怪,你怎么想?我不确定这有多奇怪,因为我们无法想象一切。试着想想名称空间:如果它是Java,你可以有
com.acme.infra.jpa.schemaUserRepository
com.acme.infra.ibatis.schemaUserRepository
,两者都将实现
com.acme.domain.UserRepository
。克莱