【问题标题】:Service layer repeating functions in repository layer存储层中的服务层重复功能
【发布时间】:2012-06-05 20:32:39
【问题描述】:

我有一个 ASP.NET MVC 应用程序,我正在使用存储库模式,以及特定于服务的存储库。我发现我的设置开始感觉非常重复。

我的图层如下所示: UserController > UserService > UserRepository(存储库然后使用实体框架)

控制器在构造函数中接受服务以实现可测试性: public UserController(IUserService userService)

服务接受存储库: public UserService(IUserRepository)

用户可能能够更新他们的业务信息、更改他们的姓名、电子邮件、删除联系地址等。

所以我最终在服务中得到了这样的东西:

public class UserService {
    User CreateUser(....);
    User GetUserById(int id);
    void UpdateUser(User user);
    void DeleteUser(User user);
    Business CreateBusiness(...);
    Business GetBusinessById(int businessId);
    void UpdateBusiness(Business business);
    void DeleteBusiness(Business business);
    IEnumerable<Business> GetBusinessesByUserId();
    IEnumerable<BusinessType> GetBusinessTypes();
    ...
    ...
    ...

这些函数中的每一个都在存储库层调用这样的函数:

public class UserRepository {
    User CreateUser(....);
    User GetUserById(int id);
    void UpdateUser(User user);
    void DeleteUser(User user);
    Business CreateBusiness(...);
    Business GetBusinessById(int businessId);
    void UpdateBusiness(Business business);
    void DeleteBusiness(Business business);
    IEnumerable<Business> GetBusinessesByUserId();
    IEnumerable<BusinessType> GetBusinessTypes();
    ...
    ...
    ...

每当我需要执行任何类型的 CRUD/数据访问操作时,我都会发现自己在执行以下操作:

  • 将操作添加到存储库的界面
  • 实现和编码存储库函数
  • 将操作添加到服务层的接口
  • 实现并编码服务函数以调用上述存储库函数

这变得很麻烦,尤其是当有多个实体与特定服务/存储库相关时。乘以整个应用程序中的多个存储库和服务...

作为背景,我放弃了通用存储库,以避免将多个存储库左右注入服务和/或控制器构造函数(或单个服务函数)的复杂性。

似乎我违反了 DRY,并且不断重复自己。这是尽可能接近,还是有更有效的方法来做到这一点?谢谢。

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-3 repository repository-pattern service-layer


【解决方案1】:

首先。服务层不应该重复存储库函数。 应该有 UserService.UpdateBasicDataUserService.UpdatePasswordUser 对象字段的子集,而不是 UserService.UpdateUser 函数。您通常不应该在服务中公开 ORM 层对象。 User 对象肯定有很多属性,UpdateUser 函数不应该改变它们,所以它不应该误认为服务使用者,它可能会改变它们。

第二。您仍然可以使用通用存储库并进行存储库聚合以进行注入。示例:

public class UserRelatedRepositories : IUserRelatedRepositories {
    IRepository<User> User { get; set; }
    IRepository<Business> Business { get; set; }
}

然后使用

UserRelatedRepositories.User.Create()

【讨论】:

  • 谢谢。如果我不向服务公开 ORM 对象,那么服务在获取用户时会返回什么?另外,如果我有一个复杂的查询需要连接多个表并返回一个 DTO,该功能是否会直接在这个更高级别的聚合存储库(您的示例中为“UserRelatedRepositories”)上实现?
  • 另外,为了可测试性,我是否必须将所有通用 IRepository 对象传递到我的聚合存储库的构造函数中,从而传递给我的控制器的构造函数?
  • @Josh:服务返回 DTO,因此它会返回带有用户属性子集的对象。对我来说,存储库是对象,仅用于简单的 CRUD 操作,因此必须在服务中进行复杂的查询。这就是为什么我的项目中的存储库返回IQueryable。为了可测试性,聚合存储库必须在构造函数中获取存储库。
  • 我想我喜欢聚合存储库的想法,以及暴露的泛型。我不知道我是否会公开 IQueryable(据我所知,这可能会导致某种我不完全理解的不需要的耦合),但否则我想我会走这条路。我最终可能会在聚合存储库中完成复杂的查询(这可能会扩展存储库的范围,但我猜你不可能全部赢)。谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-09-09
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
相关资源
最近更新 更多