如何利用ABP框架实现领域驱动设计中的更新操作实体功能?

2026-04-18 01:453阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计902个文字,预计阅读时间需要4分钟。

如何利用ABP框架实现领域驱动设计中的更新操作实体功能?

示例演示 + 更新 / 操作实体 + 一个实体一旦被创建,它将被用于示例/操作,直到它从系统中删除。可以有不同类型的实体直接或间接地更新实体。在本节中,我们将讨论更新 Issue 的多个属性。

用例演示 - 更新 / 操作实体

一旦一个实体被创建,它将被用例更新/操作,直到它从系统中删除。可以有不同类型的用例直接或间接地更改实体

在本节中,我们将讨论更改 Issue 的多个属性的典型更新操作。

这次,从更新DTO开始:

public class UpdateIssueDto { [Required] public string Title { get; set; } public string Text { get; set; } public Guid? AssignedUserId { get; set; } }

通过与 IssueCreationDto 比较,您看不到 RepositoryId 。因为,我们的系统不允许跨仓库移动问题(想想GitHub仓库)。只有 Title 是必需的,其他属性是可选的

如何利用ABP框架实现领域驱动设计中的更新操作实体功能?

让我们看看 IssueAppService 中的 Update 实现:

public class IssueAppService : ApplicationService, IIssueAppService { //省略了依赖注入 public async Task<IssueDto> UpdateAsync(Guid id, UpdateIssueDto input) { //从数据库获取问题实体 var issue = await _issueRepository.GetAsync(id); //修改标题 await _issueManager.ChangeTitleAsync(issue, input.Title); //修改分配人 if(input.AssignedUserId.HasValue) { var user = await _userRepository.GetAsync(input.AssignedUserId.Value); await _issueManager.AssignToAsync(issue, user); } //修改内容 (没有业务规则,接受任何内容) issue.Text = input.Text; // 更新实体到数据库 await _issueRepository.UpdateAsync(issue); //返回表示这个新的问题的DTO return ObjectMapper.Map<Issue, IssueDto>(issue); } }

  • UpdateAsync 方法把 id 作为一个单独的参数。它不包含在UpdateIssueDto 中。这是一个设计决策,可以帮助ABP将此服务 自动暴露 为 HTTP API 端点路由。所以,这和DDD无关

  • 首先从数据库中获取 Issue 实体。

  • 使用 IssueManagerChangeTitleAsync ,而不是直接调用 Issue.SetTitle(…) 因为我们需要实现重复的 Title 检查,就像刚才在实体创建中所做的那样。这需要对 Issue 和 IssueManager 类进行一些更改(将在下面解释)。

  • 使用 IssueManagerAssignToAsync 方法,如果分配的用户在这个请求中被更改

  • 直接设置 Issue.Text ,因为没有相关的业务规则。如果以后需要,我们总是可以进行重构

  • 将更改保存到数据库。同样,保存实体是协调业务对象和事务的应用程序服务的职责。如果 IssueManagerChangeTitleAsyncAssignToAsync 方法内部保存,将会有双数据库操作 参见讨论:为什么问题不在IssueManager中保存到数据库?

  • 最后使用 IObjectMapper 返回一个 IssueDto ,该 IssueDto 是通过映射从更新的 Issue 实体自动创建的

如前所述,我们需要对 IssueIssueManager 类进行一些更改。

首先,在 Issue 类中设置 SetTitle 为 internal:

internal void SetTitle(string title) { Title = Check.NotNullOrWhiteSpace(title, nameof(title)); }

然后在 IssueManager 中添加了一个新方法来更改标题:

public async Task ChangeTitleAsync(Issue issue, string title) { if(issue.Title == title) { return; } //如果存在相同标题的问题,直接抛错 if(await _issueRepository.AnyAsync(i => i.Title == title)) { throw new BusinessException("IssueTracking:IssueWithSameTitleExists"); } issue.SetTitle(title); }

本文共计902个文字,预计阅读时间需要4分钟。

如何利用ABP框架实现领域驱动设计中的更新操作实体功能?

示例演示 + 更新 / 操作实体 + 一个实体一旦被创建,它将被用于示例/操作,直到它从系统中删除。可以有不同类型的实体直接或间接地更新实体。在本节中,我们将讨论更新 Issue 的多个属性。

用例演示 - 更新 / 操作实体

一旦一个实体被创建,它将被用例更新/操作,直到它从系统中删除。可以有不同类型的用例直接或间接地更改实体

在本节中,我们将讨论更改 Issue 的多个属性的典型更新操作。

这次,从更新DTO开始:

public class UpdateIssueDto { [Required] public string Title { get; set; } public string Text { get; set; } public Guid? AssignedUserId { get; set; } }

通过与 IssueCreationDto 比较,您看不到 RepositoryId 。因为,我们的系统不允许跨仓库移动问题(想想GitHub仓库)。只有 Title 是必需的,其他属性是可选的

如何利用ABP框架实现领域驱动设计中的更新操作实体功能?

让我们看看 IssueAppService 中的 Update 实现:

public class IssueAppService : ApplicationService, IIssueAppService { //省略了依赖注入 public async Task<IssueDto> UpdateAsync(Guid id, UpdateIssueDto input) { //从数据库获取问题实体 var issue = await _issueRepository.GetAsync(id); //修改标题 await _issueManager.ChangeTitleAsync(issue, input.Title); //修改分配人 if(input.AssignedUserId.HasValue) { var user = await _userRepository.GetAsync(input.AssignedUserId.Value); await _issueManager.AssignToAsync(issue, user); } //修改内容 (没有业务规则,接受任何内容) issue.Text = input.Text; // 更新实体到数据库 await _issueRepository.UpdateAsync(issue); //返回表示这个新的问题的DTO return ObjectMapper.Map<Issue, IssueDto>(issue); } }

  • UpdateAsync 方法把 id 作为一个单独的参数。它不包含在UpdateIssueDto 中。这是一个设计决策,可以帮助ABP将此服务 自动暴露 为 HTTP API 端点路由。所以,这和DDD无关

  • 首先从数据库中获取 Issue 实体。

  • 使用 IssueManagerChangeTitleAsync ,而不是直接调用 Issue.SetTitle(…) 因为我们需要实现重复的 Title 检查,就像刚才在实体创建中所做的那样。这需要对 Issue 和 IssueManager 类进行一些更改(将在下面解释)。

  • 使用 IssueManagerAssignToAsync 方法,如果分配的用户在这个请求中被更改

  • 直接设置 Issue.Text ,因为没有相关的业务规则。如果以后需要,我们总是可以进行重构

  • 将更改保存到数据库。同样,保存实体是协调业务对象和事务的应用程序服务的职责。如果 IssueManagerChangeTitleAsyncAssignToAsync 方法内部保存,将会有双数据库操作 参见讨论:为什么问题不在IssueManager中保存到数据库?

  • 最后使用 IObjectMapper 返回一个 IssueDto ,该 IssueDto 是通过映射从更新的 Issue 实体自动创建的

如前所述,我们需要对 IssueIssueManager 类进行一些更改。

首先,在 Issue 类中设置 SetTitle 为 internal:

internal void SetTitle(string title) { Title = Check.NotNullOrWhiteSpace(title, nameof(title)); }

然后在 IssueManager 中添加了一个新方法来更改标题:

public async Task ChangeTitleAsync(Issue issue, string title) { if(issue.Title == title) { return; } //如果存在相同标题的问题,直接抛错 if(await _issueRepository.AnyAsync(i => i.Title == title)) { throw new BusinessException("IssueTracking:IssueWithSameTitleExists"); } issue.SetTitle(title); }