领域服务

领域服务实现领域逻辑

  • 依赖于服务和存储库。
  • 需要处理多个聚合,因为该逻辑不适合任何聚合。

领域服务与领域对象一起工作。它们的方法可以获取并返回实体、值对象、原始类型……但是,它们不获取/返回dto。dto是应用层的一部分

示例:分配问题给用户

记住问题分配是如何在问题实体中实现的

public class Issue : AggregateRoot<Guid>
{
public Guid? AssignedUserId { get; private set; } public async Task AssignToAsync(AppUser user, IUserIssueService userIssueService)
{
var openIssueCount = await userIssueService.GetOpenIssueCountAsync(user.Id); if(openIssueCount >= 3)
{
throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");
} AssignedUserId = user.Id;
} public void CleanAssignment()
{
AssignedUserId = null;
}
}

在这里,我们将把这个逻辑转移到领域服务中。

首先,修改Issue类:

public class Issue : AggregateRoot<Guid>
{
public Guid? AssignedUserId { get; internal set; }
}
  • 删除了与分配问题相关的方法。
  • 将 AssignedUserId 属性的setter从私有改为内部,以允许从领域服务设置它

下一步是创建一个名为 IssueManager 的领域服务,该服务具有AssignToAsync 来将给定问题分配给给定用户

public class IssueManager : DomainService
{
private readonly IRepository<Issue, Guid> _issueReposiroty; public IssueManager(IRepository<Issue, Guid> issueReposiroty)
{
_issueReposiroty = issueReposiroty;
} public async Task AssignToAsync(Issue issue, AppUser user)
{
var openIssueCount = await _issueRepository.CountAsync(i => i.AssignedUserId == user.Id && !i.IsClosed); if(openIssueCount >= 3)
{
throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");
} issue.AssignedUserId = user.Id;
}
}

IssueManager 可以注入任何依赖的服务,并用于查询用户的分配问题数量。

我们更喜欢并建议为领域服务使用 Manager 后缀。

这个设计的唯一问题就是 Issue.AssignedUserId 现在在类外开放设置了。然而,它不是公开的。它是内部的,并且只能在同一个程序集中(IssueTracking)进行更改。此示例解决方案的领域项目。我们认为这是合理的

  • 领域层开发人员已经知道领域规则,他们使用 IssueManager
  • 应用层开发人员已经被强制使用IssueManager,他们不直接设置它。

虽然两种方法之间存在权衡,但当业务逻辑需要使用外部服务时,我们更喜欢创建域服务

如果你没有一个好的理由,我们认为没有必要为领域服务创建接口(比如为IssueManager创建IIssueManager)

实现领域驱动设计 - 使用ABP框架 - 领域服务的更多相关文章

  1. 实现领域驱动设计 - 使用ABP框架 - 什么是领域驱动设计?

    前言: 最近看到ABP官网的一本电子书,感觉写的很好,翻译出来,一起学习下 (Implementing Domain Driven Design) https://abp.io/books DDD简介 ...

  2. 实现领域驱动设计 - 使用ABP框架 - 通用准则

    在进入细节之前,让我们看看一些总体的 DDD 原则 数据库提供者 / ORM 无关性 领域和应用程序层应该与 ORM / 数据库提供程序 无关.它们应该只依赖于 Repository 接口,而 Rep ...

  3. 实现领域驱动设计 - 使用ABP框架 - 解决方案概览

    .NET解决方案的分层 下图显示了使用ABP的 应用启动模板 创建的Visual Studio解决方案: 解决方案名称为问题跟踪,它由多个项目组成.通过考虑DDD原则以及开发和部署实践,该解决方案是分 ...

  4. 实现领域驱动设计 - 使用ABP框架 - 存储库

    存储库 Repository 是一个类似于集合的接口,领域层和应用程序层使用它来访问数据持久性系统(数据库),以读写业务对象(通常是聚合) 常见的存储库原则是: 在领域层定义一个存储库接口(因为它被用 ...

  5. 实现领域驱动设计 - 使用ABP框架 - 创建实体

    用例演示 - 创建实体 本节将演示一些示例用例并讨论可选场景. 创建实体 从实体/聚合根类创建对象是实体生命周期的第一步.聚合/聚合根规则和最佳实践部分建议为Entity类创建一个主构造函数,以保证创 ...

  6. 基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑

    目录 系列文章 领域逻辑和应用逻辑 多应用层 示例:正确区分应用逻辑和领域逻辑 学习帮助 系列文章 基于ABP落地领域驱动设计-00.目录和前言 基于ABP落地领域驱动设计-01.全景图 基于ABP落 ...

  7. 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇

    前言 领域驱动设计,其实已经是一个很古老的概念了,但它的复杂度依旧让学习的人头疼不已. 互联网关于领域驱动的文章有很多,每一篇写的都很好,理解领域驱动设计的人都看的懂. 不过,这些文章对于那些初学者而 ...

  8. .net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇

    .net core +codefirst(.net core 基础入门,适合这方面的小白阅读)   前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以. ...

  9. 基于ABP落地领域驱动设计-00.目录和小结

    <实现领域驱动设计> -- 基于 ABP Framework 实现领域驱动设计实用指南 翻译缘由 自 ABP vNext 1.0 开始学习和使用该框架,被其优雅的设计和实现吸引,适逢 AB ...

  10. 基于ABP落地领域驱动设计-05.实体创建和更新最佳实践

    目录 系列文章 数据传输对象 输入DTO最佳实践 不要在输入DTO中定义不使用的属性 不要重用输入DTO 输入DTO中验证逻辑 输出DTO最佳实践 对象映射 学习帮助 系列文章 基于ABP落地领域驱动 ...

随机推荐

  1. 编译树莓派Linux内核

    1.建议边看视频边跟着教程走 https://www.bilibili.com/video/av91990721?zw 2.准备工作 下载官方提供的交叉编译工具链 git clone https:// ...

  2. Asp.net Core Kestrel 免费实现https

    0.概述 先了解下https是个啥: https://www.bilibili.com/video/BV1j7411H7vV so!只要给我们的web服务器配置一个证书就行了,证书可以买,也可以用免费 ...

  3. git撤销远已经push到程服务器上某次提交

    git撤销远已经push到程服务器上某次提交 问题: 不小心把一次错误的代码push到远程服务器上的分支上,或者没有merge强制将本地的方法push到git服务器上. 解决方法: 输入 git lo ...

  4. 2020年最新版区块链面试题1-copy

    1. 什么是区块链? 回答:区块链是不间断的经济交易数字分类帐,可以进行编程,以记录不仅是金融交易,还可以记录几乎所有有价值的东西.简单来说,它是一个不可变记录的分散式分布式数据库,该数据库由计算机集 ...

  5. javaIO类--File类

    -------------------- File类 是对文件系统中文件以及目录(文件夹)进行封装的对象,可以通过面向对象的思想来操作文件和目录(文件夹).File类保存文件或目录的各种元素的信息,包 ...

  6. ClustrixDB-new数据库

    ClustrixDB是一种集群式RDBMS,可确保事务处理符合ACID特性,同时可轻松的提供可扩展性和容错能力. ClustrixDB集群由三个或更多节点(联网的同构服务器)组成.ClustrixDB ...

  7. HBase-3rowkey的设计

    HBase表热点 1 什么是热点 检索habse的记录首先要通过row key来定位数据行. 当大量的client访问hbase集群的一个或少数几个节点,造成少数region server的读/写请求 ...

  8. C# LinkedList 删除元素

    开发中经常有任务队列的设计,主要用于存储待执行的任务.由于任务来源的多样性,因此有时候需要一颗后悔药,将队列中某些待执行任务删除.此时使用LinkedList比较合适. public LinkedLi ...

  9. 自定义Ollama安装路径

    由于Ollama的exe安装软件双击安装的时候默认是在C盘,以及后续的模型数据下载也在C盘,导致会占用C盘空间,所以这里单独写了一个自定义安装Ollama安装目录的教程. Ollama官网地址:htt ...

  10. 一种把dump里连续的内存保存到文件的方法

    前几天调试一个崩溃,截到一个full dump文件,显示一个视频帧数据转换有问题.从调用栈可以看到完整的帧数据. 然后我就想把这个数据保存下来,再构造崩溃场景,VS没有提供把内存dump为文件的功能. ...