首页 > 解决方案 > 如何扩展服务层方法

问题描述

我们正处于开发应用程序的设计阶段。

我们决定实施面向 DDD 的设计。

我们的应用程序有一个服务层。

服务中的每个方法都有自己的任务。

样本

让我们考虑一个用户服务。

此方法获取所有用户

public User GetAll()
{
   //codes
}

现在,如果我想按名称对所有用户进行排序。

选项1

使用另一种方法

public User GetAllAndOrderByAsc()

或者

public User GetAllAndOrderByDesc()

针对不同的情况采取不同的方法。

看起来一点都不好

选项 2

在 Api 或 Application 级别继续查询

public IQueryable<User> GetAll()
{
    //codes
}

API 或应用程序级别

var users = from u in _userService.GetAll()
            select u;

switch (sortOrder)
{
    case "name_desc":
        users = users.OrderByDescending(u => u.Name);
        break;
    case "name_asc":
        users = students.OrderBy(u => u.Name);
        break;
    default:
        users = students.OrderBy(u => u.Name);
        break;
}

我想到的选项仅限于这些。

我是在某处犯错还是无法掌握逻辑。你能帮我吗?

标签: c#design-patterns

解决方案


你没疯:这是一个常见的问题,你列出的选项是合法的,每个都有优点和缺点,并且在实践中很常用。

根据您的应用程序的上下文,理论上可以一直公开IQueryable<>到表示层(例如,如果您正在运行 Web 服务,则使用 OData)。但我发现对 API 进行更多控制会更明智,以避免有人通过基本上下载整个数据库的请求访问端点。

在您的服务层中,您需要考虑您真正希望人们使用哪些用例。

  • 很少有人真正需要查看所有用户:这可能只发生在它是导出过程的一部分时,而不是返回一个集合,您可能希望返回一个IObservable当它们从数据库的流中出现时将它们推出的集合.
  • 更多情况下,您会希望一次获得一个用户页面以显示在 UI 中。这可能还需要对其应用排序和搜索。
  • 您几乎肯定会想要一种方法来获取您已经知道其 ID 的用户(可能是从分页列表中挑选的)。
  • 您可能还期望需要根据特定条件进行查询。也许人们通常应该只看到“活跃”用户。也许他们应该考虑特定的用户分组。

根据我的经验,让我的服务层代表这些关于应用程序应该如何思考事物的域级假设,并编写支持您实际想要支持的用例的接口,即使这意味着您经常发现自己添加新的服务方法以支持新功能。例如:

Task<IReadOnlyCollection<User>> GetPageOfActiveUsersAsync(
    PagingOptions pagingOptions, 
    SortOptions sortOptions, 
    string searchTerm, 
    IReadOnlyCollection<int> organizationIds);
Task<User> GetActiveUserByUsernameAsync(string username);
Task<User> GetActiveUserByIdAsync(int userId);
IObservable<User> GetAllUsersForAuditExport();

我目前从事的项目使用这样的类:

public class SortSettings
{
    public string SortField { get; set; }
    public SortDirection SortDirection { get; set; } = SortDirection.Asc;
}

然后,根据我们查询的内容,我们可以使用反射、switch语句或其他一些机制来选择 SortExpression ( Expression<Func<TSource, TResult>>),然后像这样应用排序:

query = sortOptions.SortDirection == SortDirection.Asc 
    ? query.OrderBy(sortExpression)
    : query.OrderByDescending(sortExpression);

如果你发现你在很多地方都在使用它,那么这个逻辑很容易提取到一个单独的方法中。

您可能会发现搜索和分页等其他常见功能需要类似的方法。


推荐阅读