2014-07-10 23 views
2

存储库实现是我的域模型的一部分,还是我应该只将它们抽象为我的域的一部分?存储库实现是我的域的一部分吗?存储库是否有SQL查询?

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

感谢

更新 Illustration

更新2 请看看:如果您使用的是六边形,洋葱或端口和适配器建筑风格http://leocavalcante.github.io/patterns/2014/07/11/repository-pattern-and-database-schema.html

+1

只有抽象是你的域的一部分。您应该可以在不破坏域名的情况下更换实施。存储库实现可以包含原始SQL,对ORM具有依赖关系,无论如何。 http://www.jefclaes.be/2014/01/repositories-where-did-we-go-wrong_26.html – JefClaes

+0

@JefClaes你对此有何看法? http://yuml.me/1f5c9114 –

+1

从你发布的图表看来,你应该有一个'UserRepository'接口和两个实现它的具体类:'SchemaAUserRepository'和'SchemaBUserRepository'。然后使用控制反转,可以将适当的资源库注入工厂。 –

回答

5

,那么通常的做法是将您的存储库接口放入您的域模型中,并将您的存储库实现放入持久层/ ada中PTER。然后,您将使用IoC容器连接它们,并将持久层的引用添加到您的域模型中。这使您可以在持久层中使用域模型实体和值对象,但也可以通过IoC访问域模型中的存储库。

如果你把你的SQL取决于你,这不是特别的DDD的事情,但它可能属于你的仓库。标准做法是使用存储过程或使用ORM(如Entity Framework或NHibernate)的LINQ样式查询。在后面的例子中,查询将存在于存储库中。

好的做法是让您的存储库接受域实体(即创建/更新)并返回域实体(即查询)。由ORM生成的任何自动生成的实体通常会被您的存储库隐藏。这看起来可以消除很多从ORM中获得的“优点”(如懒惰加载和双向导航属性),但这些往往是妨碍良好DDD的障碍,特别是良好的对象/实体设计。

额外的细节

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

在DDD中,您最好希望每个聚合根目录有一个存储库。例如,坚持一个聚合根(聚合根可能是单个实体,或者由其他实体或值对象组成的实体)可能会导致写入4个单独的表。

+0

我的Repository知道我的数据库模式是一件坏事吗?因为如果我使用不同的模式实现另一个数据库,那么我知道“用户”表的知识库现在无法处理'tbl_users'。如何避免这种情况,每个数据库模式的一个Repository实现? –

+0

查看我编辑的答案以获取更多信息。 –

+0

请看看:http://leocavalcante.github.io/patterns/2014/07/11/repository-pattern-and-database-schema.html –

1

是的,资源库的实现绝对可以成为你的域模型的一部分。例如,在域驱动设计中,实现存储库时的主要目标是关注消耗存储库的代码的视角,而不是存储库本身的代码。

Domain Driven Design book,PG 155:

实现一个库

实施,将大大不同,这取决于所使用的技术为持久性,你有基础设施 。理想的是 隐藏客户端的所有内部工作(尽管不是来自客户端的 开发人员),因此客户端代码将是相同的,无论 数据存储在对象数据库中,存储在关系数据库 中,或者只是保存在内存中。

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

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

+0

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

相关问题