存储库模式 - 构建存储库

Repository Pattern - Structuring repositories

我正在尝试在我的 MVC 程序设计中使用存储库,但我 运行 遇到了如何最好地构建它们的问题。

例如,假设我有一个对象 USers 和一个 UserRepository,它具有 getUser(int id)saveUser(Dal.User model) 等功能...

因此,如果在我的控制器中我有 EditUser,并且我想显示一个包含用户详细信息输入表单的视图。所以我可以这样做:

User user = _userRepository.getUserDetails(userId);

好处是我的控制器只处理处理 HTTP 请求,业务逻辑被移动到存储库,使测试等更容易

所以,假设我想显示一个下拉列表,其中包含此用户在我的系统中可能拥有的角色,即客户、管理员、员工等

在 _userRepository 中有一个名为 getPossibleUserRoles() 的函数是否可以,或者我应该有一个单独的 _roleRepository 和函数 getRoles() 吗?

将您遇到的每个实体的存储库注入到您的控制器中是个坏主意吗?或者在你的存储库中混合实体是不是一个坏主意,使它们变得混乱。

我意识到我提出了一个非常简单的场景,但显然随着系统复杂性的增加,您可能会谈到需要在控制器中为每个页面调用实例化 10 个存储库。并且还可能实例化当前控制器方法中未使用的存储库,只是为了让它们可用于其他控制器方法。

任何关于如何最好地使用存储库构建项目的建议表示赞赏

is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?

两种解决方案都可以接受,但请考虑您将如何控制存储库和这些存储库上的方法的扩散。恕我直言,典型的存储库使用场景往往会以太多的存储库结束,每个存储库都有太多的方法。 DDD 提倡每个聚合根一个存储库。这是一个很好的经验法则...如果您遵循 DDD 原则。

IS it a bad idea to inject a repository for every entity you encounter into your controller? or is it a bad idea to mix entities inside your repositories, making them cluttered.

注入可变依赖项,所以是的,为您的控制器需要的每个实体注入一个存储库。然而,一旦您开始注入四个以上的依赖项,您很可能在设计中的某处遗漏了抽象。有些人用 RepositoryFactory 解决了这个问题,但可以说,这引入了不透明依赖关系的问题,恕我直言,未能传达 class 的真正依赖关系,降低了它的可用性和自文档能力。

看看在控制器中使用查询对象而不是存储库 (https://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/, etc.) and take a look at using orchestration/mediation (http://codeopinion.com/thin-controllers-cqrs-mediatr/)。我认为您会发现更好的设计出现,可以帮助您解决设计问题。

is it ok to have a function in the _userRepository called getPossibleUserRoles() or should I have a seperate _roleRepository with a function getRoles() ?

假设您有一些控制器调用:

_userRepository.getUserDetails(userId);

但他们从不打电话:

_userRepository.getPossibleUserRoles(userId);

那么你就是在强迫你的控制器依赖于它们不使用的方法。

所以这不就可以了,你应该分开这个。

但是如果 getUserDetailsgetPossibleUserRoles 是选择性的(共享相同的实体,共享相同的业务逻辑等)。

除了为 Roles.

创建新的 class 之外,您可以在不更改 userrepository 实现的情况下拆分它
public class UserRepsitory : IUserRoles, IUserRepository
{

} 

I realise I have presented a very simplistic scenario, but obviously as systems grow in complexity you are potentially talking of 10s of repositories needing to be instantiated in a controller

如果构造函数获取过多参数,则很可能违反 SRP。 Mark Seemann 在 here.

中展示了如何解决这个问题

简而言之:在创建行为时,如果您总是同时使用 2 个或更多存储库。然后,这些存储库非常接近。所以你可以创建一个服务并在这个服务中编排它们。之后,除了在控制器构造函数中使用 2 个或更多存储库之外,您还可以将此服务用作参数。