【问题标题】:Best practice for performing sequential MediatR commands/queries as part of a single HTTP Request?作为单个 HTTP 请求的一部分执行顺序 MediatR 命令/查询的最佳实践?
【发布时间】:2019-07-23 14:58:49
【问题描述】:

我处于创​​建实体需要其他实体的创建和 ID 的情况,但是,我不确定如何最好地使用 MediatR 来实现。

例如,假设我有一个用户对象...

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public ICollection<Submission> Submissions { get; set; }
}

提交对象...

public class Submission
{
    public int Id { get; set; }
    public string Reference { get; set; }
    public User User { get; set; }
    public ICollection<QuestionsAndAnswer> QuestionAndAnswers { get; set; }
}

还有一个 QuestionAndAnswer 对象。

public class QuestionAndAnswer
{
    public int ID { get; set; }
    public string Question { get; set; }
    public string Answer { get; set; }
    public Submission { get; set; }
}

每个用户可以有多个提交,每个提交有多个问题和答案。

在这种情况下,用户已经完成了一系列问题,提供了答案,填写了提供联系方式的最终表格,然后将信息提交给 API。在这一点上,我不确定如何使用 MediatR 处理数据,因为必须创建用户,并返回他们的 ID 作为结果来创建提交对象,这反过来又是必需的,以便可以保存问题和答案。

我是否应该实现一个名为 CreateUserWithSubmissionQuestionAndAnswersCommand 的命令,该命令的处理程序然后以某种方式调用三个单独命令的处理程序并按顺序执行它们,如果可以,如何执行?

我对如何在不违反 CQRS 的情况下将这个场景实现为单个 HTTPRequest 有点迷茫。我能想到的唯一另一种方法是实现单独的端点,它们分别执行这些任务中的每一个,这需要客户端连续发出和接收三个单独的调用(CreateUser、CreateSubmission、CreateQuestionAndAnswer)?

有人有什么想法吗?

【问题讨论】:

  • 我也面临这个问题,我目前正在我的控制器中链接处理程序调用。
  • @AntonToshik 我同意,这似乎是目前最好的解决方案。
  • @RobJackStewart 你有没有找到一个“更好”的解决方案?
  • @AdamStapleton 这一切都归结为用例,因为我已经使用了标记的答案和我从其他处理程序调用处理程序的原始建议。我更喜欢后一种选择,但请遵守严格的规则,即您只能深入两层。例如你可以让一个处理程序调用另一个,但你不能让第二个 hadnelr 调用第三个,因为这意味着你的处理程序不是 atmoic。

标签: c# asp.net-core cqrs command-pattern mediatr


【解决方案1】:

我通常将用户交互/用户故事建模为 MediatR 请求。在大多数情况下,这意味着将单个 HTTP 请求映射到单个 MediatR 请求。

在您的情况下,这将是一个封装提交处理的单个请求,例如ProcessSubmissions。该请求将包含用户的属性以及提交和相关的问题/答案对。然后,单个处理程序将以正确的顺序保存各个实体。

为了完整起见,此解决方案可能如下所示:

public class ProcessSubmission : IRequest
{
    public User User { get; set; }

    public ICollection<Submission> Submissions { get; set; }
}

public class ProcessSubmissionHandler : IRequestHandler<ProcessSubmission>
{
    public async Task<Unit> Handle(ProcessSubmission request, CancellationToken cancellationToken)
    {
        // Persist the user in the database
        var userId = PersistTheUser(request.User);

        foreach (var submission in request.Submissions)
        {
            // Persist each submission with questions and answers
        }
    }
}

【讨论】:

    猜你喜欢
    • 2018-05-25
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 2023-03-08
    • 2021-03-31
    • 2011-03-12
    • 2021-05-07
    • 1970-01-01
    相关资源
    最近更新 更多