实现领域驱动设计 – 使用ABP框架 – 更新操作实体


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

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

在本节中,我们将讨论更改 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 是必需的,其他属性是可选的

让我们看看 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);
}

原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/270251.html

(0)
上一篇 2022年6月24日
下一篇 2022年6月24日

相关推荐

发表回复

登录后才能评论