存储库模式问题

时间:2009-09-01 22:00:08

标签: database design-patterns repository-pattern

我正在构建一个ASP.NET MVC应用程序,我正在使用存储库来存储和检索视图对象。我的问题是,各种存储库的实现是否可以相互调用? I.E. ICustomerRepository实现可以调用IAddressRepository的实现,还是应该处理自己对地址数据源的更新?

编辑:

谢谢大家,客户/地址示例并不真实。实际问题涉及三个聚合,它们更新第四个聚合以响应其各自状态的变化。在这种情况下,引入依赖关系与违反不重复自己原则之间似乎存在冲突。

3 个答案:

答案 0 :(得分:3)

您应该拥有每个聚合根的存储库。

我不了解您的域模型,但我觉得拥有IAddressRepository并不自然。除非“地址”是您域中的聚合根。

事实上,在大多数情况下,“地址”甚至不是实体,而是价值对象。也就是说,在大多数情况下,“地址”的标识由其值(其所有属性的值)决定;它没有单独的'Id'(键)字段 因此,在这种情况下,CustomerRepository应负责存储Address,因为Address是Customer聚合根的一部分。

编辑(好的,所以你的情况只是一个例子):

但是,如果您还有其他情况需要存储库中的另一个存储库,那么我认为最好从该存储库中删除该功能,并将其放在单独的类(服务)中。 我的意思是:我认为,如果你在存储库A中有一些功能,它依赖于另一个存储库B,那么这种功能不属于存储库A. 相反,在实现此功能的地方编写另一个类(在DDD中称为服务)。

无论如何,我认为存储库不应该真正相互调用。但是,如果您不想编写服务,并且您确实希望将该逻辑保留在存储库本身中,那么将另一个存储库作为该特定方法中的参数传递。

我希望自己有点清楚。 :P

答案 1 :(得分:2)

他们真的不应该互相打电话。存储库是您希望在域上执行的(或多或少)原子操作的抽象。他们拥有的依赖越少越好。实际上,存储库的任何使用者都应该能够将存储库类指向数据库并让它在没有大量配置的情况下执行必要的域操作。

它们还应代表您域中的“聚合” - 即许多功能将基于的关键焦点。我想知道为什么你会有一个单独的地址信息库?这不应该是您的客户存储库的一部分吗?

答案 2 :(得分:1)

这取决于存储库的类型(或至少后果如何),但一般情况下,如果您有相互调用的数据存储库,您将遇到诸如周期性的问题(repo A - >需要B - >需要C - .oops,需要A)或递归数据加载(A->需要B& C - > C-需要D,E - > .... - > .. ad nauseum)。测试也变得更加困难。

例如,您需要加载地址存储库以正确运行客户存储库,因为客户存储库会调用地址存储库。如果您需要测试客户仓库,则需要对地址进行db加载或以某种方式对其进行模拟,最终您将无法加载和测试任何单个系统存储库而无需加载它们。

拥有这些依赖性也是一种阴险,因为它们通常不清楚 - 通常你将存储库作为一个数据保持抽象 - 如果你必须意识到它们如何相互依赖你可以'使用它们作为抽象,但每当你想使用它们时都必须管理加载过程。