当在 Repository/UnitOrWork 之上使用 Service 类时,我应该在哪里放置逻辑不适合 Repository 的常用数据访问代码?

2024-06-19

In my 先前的问题 https://stackoverflow.com/questions/24906548/using-the-generic-repository-unit-of-work-pattern-in-large-projects我询问如何为使用 EF 等 ORM 框架构建的大型应用程序实现存储库/工作单元模式。

我现在无法解决的一个后续问题是在哪里放置包含业务逻辑的代码,但仍然较低级别足以在应用程序的许多其他部分中普遍使用。

例如,这里有一些这样的方法:

  • 让所有用户担任一种或多种角色。
  • 获取用户在可选范围内拥有特权的所有城市 地区。
  • 获取给定设备类型内给定设备的所有测量设备 当前用户拥有权限的区域。
  • 通过代码查找产品,检查它是否可见并抛出 如果未找到或不可见则异常。

所有这些方法都使用 UnitOfWork 进行数据访问或操作,并按照其规范接收多个参数。我认为每个人都可以为大型项目中的此类常见任务编写更多示例。我的问题是我应该把这些方法实现放在哪里?我目前可以看到以下选项。

选项 1:每个方法都进入其自己的服务类

public class RegionServices {

  // support DI constructor injection
  public RegionServices(IUnitOfWork work) {...}
  ...
  public IEnumerable<City> GetCitiesForUser(User user, Region region = null) { ... }
  ...
}

public class DeviceServices {
  // support DI constructor injection
  public DeviceServices(IUnitOfWork work) {...}
  ...
  public IEnumerable<Device> GetDevicesForUser(User user, DeviceType type, Region region = null) { ... }
  ...
}

我不喜欢的是,如果更高级别的应用程序服务需要调用例如 3 个或这些方法,那么它需要实例化 3 个服务,如果我使用 DI,那么我什至必须将所有 3 个服务放入构造函数,很容易产生相当多的代码味道。

选项 2:为此类公共数据访问创建某种 Facade

public class DataAccessHelper {

  // support DI constructor injection
  public DataAccessHelper(IUnitOfWork work) {...}
  ...
  public IEnumerable<City> GetCitiesForUser(User user, Region region = null) { ... }
  public IEnumerable<Device> GetDevicesForUser(User user, DeviceType type, Region region = null) { ... }
  public IEnumerable<User> GetUsersInRoles(params string[] roleIds) { ... }
  ...
}

我不喜欢它,因为它感觉违反了 SRP,但它的使用可以更舒适。

选项 3:为存储库创建扩展方法

public static class DataAccessExtensions {
  public static IEnumerable<City> GetCitiesForUser(this IRepository repo, User user, Region region = null) { ... }
}

Here IRepository是一个具有通用方法的接口,例如Query<T>, Save<T>等等。我也不喜欢它,因为感觉就像我想为存储库提供业务逻辑,据我所知这是不可取的。然而,它表达了这些方法是通用的,并且比服务类级别低,这是我喜欢的。

也许还有其他选择?...谢谢您的帮助。


如果您说某个领域逻辑需要查看 3 条不同的信息才能做出决定,那么我们需要向它提供这些信息。

此外,如果我们说这些不同的部分中的每一个都可以对该领域的其他部分有用,那么它们中的每一个也都需要有自己的方法。我们可以根据您的领域/设计来讨论每个查询是否需要放置在单独的类中。

我想说的一点是,将有一个应用程序服务委托给一个或多个 Finder 类(存放查询的类),这些类仅存放查询,然后累积结果并将其传递给域服务,如下所示:方法参数.

域服务根据接收到的参数执行逻辑并返回结果。这样域服务就可以轻松测试。

伪代码

App Service
result1 = finder.query1()
result2 = finder.query2()
result3= yetanotherfinder.query();
domainresult = domainservice.calculate(result1,result2,result3);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当在 Repository/UnitOrWork 之上使用 Service 类时,我应该在哪里放置逻辑不适合 Repository 的常用数据访问代码? 的相关文章

随机推荐