gpt4 book ai didi

c# - 在 Repository/UnitOrWork 之上使用服务类时,我应该将逻辑不适合 Repository 的常用数据访问代码放在哪里?

转载 作者:太空宇宙 更新时间:2023-11-03 15:53:11 28 4
gpt4 key购买 nike

在我的earlier question我问的是如何为使用 EF 等 ORM 框架构建的大型应用程序实现存储库/工作单元模式。

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

例如这里有几个这样的方法:

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

所有这些方法都使用 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) { ... }
...
}

我不喜欢的是,如果更高级别的应用程序服务需要调用 example 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) { ... }
}

在这里IRepository是具有通用方法的接口(interface),如 Query<T> , Save<T>等。我也不喜欢它,因为我觉得我想将业务逻辑提供给存储库,这是不可取的 AFAIK。但是,它表达了这些方法是通用的并且比服务类更低级别,我喜欢这一点。

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

最佳答案

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

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

我想说的是,将有一个应用程序服务委托(delegate)给一个或多个 Finder 类(您的查询所在的类),这些类仅包含查询,然后累积结果并将其传递给域服务作为方法参数。

域服务作用于接收到的参数执行逻辑并返回结果。这样域服务很容易测试。

伪代码

App Service
result1 = finder.query1()
result2 = finder.query2()
result3= yetanotherfinder.query();
domainresult = domainservice.calculate(result1,result2,result3);

关于c# - 在 Repository/UnitOrWork 之上使用服务类时,我应该将逻辑不适合 Repository 的常用数据访问代码放在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24913705/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com