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>
等等。我也不喜欢它,因为感觉就像我想为存储库提供业务逻辑,据我所知这是不可取的。然而,它表达了这些方法是通用的,并且比服务类级别低,这是我喜欢的。
也许还有其他选择?...谢谢您的帮助。