存储库模式 - 构建存储库

时间:2016-10-20 08:35:06

标签: oop design-patterns repository-pattern

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

作为一个例子,假设我有一个对象USers,我有一个UserRepository,它有getUser(int id)saveUser(Dal.User model)等函数......

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

User user = _userRepository.getUserDetails(userId);

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

所以,我想要显示一个下拉列表,列出该用户可能在我的系统中拥有的角色,即客户,管理员,员工等

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

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

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

有关如何使用存储库构建项目的最佳建议

2 个答案:

答案 0 :(得分:1)

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

Both solutions are acceptable but consider how you're going to control the proliferation of repositories and methods on those repositories. IMHO, the typical repository usage scenario tends to end-up with too many repositories with too many methods on each. DDD advocates a repository per aggregate root. This is a good rule of thumb... if you're following DDD principles.

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.

Inject volatile dependencies, so yes, inject a repository for every entity your controller needs. However, once you start injecting more than four dependencies, chances are you've missed an abstraction somewhere in your design. Some solve this problem with RepositoryFactory but this, arguably, introduces the problem of opaque dependencies and, IMHO, fails to convey the class's real dependencies, reducing its usability and self-document-ability.

Take a look at using query objects rather than repositories (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/) in your controllers. I think you'll find a better design emerges that will help you with your design issues.

答案 1 :(得分:1)

  

可以在_userRepository中调用一个函数   getPossibleUserRoles()或者我应该有一个单独的_roleRepository   使用函数getRoles()?

让我们说你有一些控制器电话:

_userRepository.getUserDetails(userId);

但他们从不打电话:

_userRepository.getPossibleUserRoles(userId);

然后你强迫你的控制器依赖他们不使用的方法。

说它不仅仅是好的,你应该拆分它。

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

除了为Roles创建新类之外,您可以在不更改userrepository实现的情况下拆分它。

public class UserRepsitory : IUserRoles, IUserRepository
{

} 
  

我意识到我提出了一个非常简单的场景,但很明显   随着系统复杂性的增长,你可能会谈论10个问题   需要在控制器中实例化的存储库

如果构造函数的参数太多,则存在高可靠性SRP违规。 Mark Seemann在here中展示了如何解决这个问题。

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