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

时间:2014-07-10 14:53:38

标签: domain-driven-design

Repository实现是我的域模型的一部分还是我应该只将它们的抽象部分作为我的域的一部分?

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

由于

更新 Illustration

更新2 请看一下:http://leocavalcante.github.io/patterns/2014/07/11/repository-pattern-and-database-schema.html

2 个答案:

答案 0 :(得分:7)

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

你把SQL放在哪里,这不是特别的DDD,但它可能属于你的知识库。标准做法是使用ORM(如Entity Framework或NHibernate)来使用存储过程或LINQ样式查询。在后一种情况下,查询将存在于存储库中。

良好做法是让您的存储库接受域实体(即用于创建/更新)并返回域实体(即用于查询)。由ORM生成的任何自动生成的实体通常都会被您的存储库隐藏。这似乎可以解决你从ORM中获得的很多“好处”(比如延迟加载和双向导航属性),但是这些事情通常会阻碍良好的DDD和特别好的对象/实体设计。

额外明细

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

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

答案 1 :(得分:1)

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

Domain Driven Design book,第155页:

  

实施存储库

     

根据技术的不同,实施情况会有很大差异   用于持久性和您拥有的基础设施。理想的是   隐藏客户端的所有内部工作(尽管不是来自客户端)   客户端的开发人员),以便客户端代码是否相同   数据存储在对象数据库中,存储在关系中   数据库,或者只是保存在内存中。

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

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