c# - 如何扩展服务层方法
问题描述
我们正处于开发应用程序的设计阶段。
我们决定实施面向 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;
}
我想到的选项仅限于这些。
我是在某处犯错还是无法掌握逻辑。你能帮我吗?
解决方案
你没疯:这是一个常见的问题,你列出的选项是合法的,每个都有优点和缺点,并且在实践中很常用。
根据您的应用程序的上下文,理论上可以一直公开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);
如果你发现你在很多地方都在使用它,那么这个逻辑很容易提取到一个单独的方法中。
您可能会发现搜索和分页等其他常见功能需要类似的方法。
推荐阅读
- python - 将 scala 中的伴随对象转换为 Python
- java - 无法选择选择框
- apache-cloudstack - Cloudstack虚拟路由器未启动
- azure - Microsoft Azure 中的 Functions Bot、Web App Bot 和 Bot Channels 注册之间的区别?
- r - data.table 引用语义:遍历所有列的内存使用情况
- javascript - Javascript 中 Cron 表达式的正则表达式
- javascript - history.pushState() 导致浏览器导航
- c++ - 将对象添加到数组时的 EXC_BAD_ACCESS
- google-cloud-functions - GCP 函数 http 触发器返回:600 - 回调不可调用
- android-emulator - 没有USB设备android studio 3.1.3