如何正确使用存储库模式?

cho*_*bo2 86 .net c# asp.net asp.net-mvc repository-pattern

我想知道我应该如何分组我的存储库?就像我在asp.net mvc和我的书中看到的例子一样,他们基本上每个数据库表使用一个存储库.但是,这似乎是很多存储库导致您必须稍后调用许多存储库来进行模拟和填充.

所以我猜我应该把它们分组.但是我不确定如何将它们分组.

现在我做了一个注册存储库来处理我的所有注册内容.然而,在我有3个存储库来执行此操作之前,我需要更新4个表.

例如,其中一个表是许可证表.当他们注册时,我查看他们的密钥并检查它是否存在于数据库中.现在如果我需要在注册之外的其他位置检查此许可证密钥或该表中的其他内容会发生什么?

一个点可能是登录(检查密钥是否未过期).

那么在这种情况下我该怎么做?再次重写代码(打破DRY)?尝试将这两个存储库混合在一起并希望在其他一些时间点不需要任何方法(例如,我可能有一个检查userName是否被使用的方法 - 也许我会在其他地方需要它).

此外,如果我将它们合并在一起,我要么需要2个服务层才能进入同一个存储库,因为我认为网站的2个不同部分的所有逻辑都很长,我必须有像ValidateLogin(),ValdiateRegistrationForm()这样的名称,ValdiateLoginRetrievePassword()等

或者反正调用存储库,只是有一个奇怪的声音名称?

似乎很难创建一个具有足够通用名称的存储库,因此您可以将它用于应用程序的许多位置并且仍然有意义,我不认为在存储库中调用另一个存储库是一个好习惯吗?

Arn*_*psa 41

在使用存储库模式时我做错了一件事 - 就像你一样,我认为该表与存储库1:1有关.当我们从域驱动设计中应用一些规则时 - 分组存储库问题经常会消失.

存储库应该是每个聚合根而不是表.这意味着 - 如果实体不应该独自生活(即 - 如果你有一个Registrant特定参与者Registration) - 它只是一个实体,它不需要一个存储库,它应该通过聚合根存储库来更新/创建/检索它所属.

当然 - 在许多情况下,这种减少存储库数量的技术(实际上 - 它更像是一种构建域模型的技术)无法应用,因为每个实体都应该是一个聚合根(这在很大程度上取决于你的域,我只能提供盲目的猜测.在您的示例中 - License似乎是聚合根,因为您需要能够在没有Registration实体上下文的情况下检查它们.

但这并不限制我们级联存储库(如果需要,存储库Registration可以引用License存储库).这并不限制我们License直接从Registration对象引用存储库(最好是通过IoC).

尽量不要通过技术提供的复杂性或误解某些东西来推动您的设计.ServiceX仅仅因为您不想构建2个存储库而对存储库进行分组并不是一个好主意.

更好的是给它一个合适的名字 - RegistrationService

但是一般应该避免服务 - 它们通常是导致贫血领域模型的原因.

编辑:
开始使用IoC.它真正减轻了注入依赖关系的痛苦.
而不是写:

var registrationService = new RegistrationService(new RegistrationRepository(),  
      new LicenseRepository(), new GodOnlyKnowsWhatElseThatServiceNeeds());
Run Code Online (Sandbox Code Playgroud)

你可以写:

var registrationService = IoC.Resolve<IRegistrationService>();
Run Code Online (Sandbox Code Playgroud)

Ps最好使用所谓的公共服务定位器,但这只是一个例子.

  • 哈哈哈......我正在建议使用服务定位器.总是欣喜地看到我过去的愚蠢. (17认同)
  • @ngm自从我回答这个问题后发生了很多变化.我仍然同意聚合根应该绘制事务边界(作为一个整体保存),但我对使用存储库模式抽象持久性不太乐观.最近 - 我只是直接使用ORM,因为像热切/懒惰的加载管理这样的东西太尴尬了.专注于开发富域模型而不是专注于抽象持久性更有利. (10认同)
  • @Developer不,不完全是.他们仍然应该坚持无知.您从外部检索聚合根并在其上调用方法来执行该作业.我的域模型没有引用,只是标准的.net框架.要实现这一点,你必须拥有足够聪明的丰富的域模型和工具(NHibernate可以做到这一点). (2认同)

neo*_*r99 5

我开始做的一件事就是实际开发包装N个存储库的服务.希望您的DI或IoC框架可以帮助您更轻松地实现这一目标.

public class ServiceImpl {
    public ServiceImpl(IRepo1 repo1, IRepo2 repo2...) { }
}
Run Code Online (Sandbox Code Playgroud)

那有意义吗?此外,我理解在这个庄园中提及服务可能会或可能不会实际符合DDD原则,我只是这样做,因为它似乎有效.