【问题标题】:Why do CQRS command handlers exclude saving UnitOfWork?为什么 CQRS 命令处理程序排除保存 UnitOfWork?
【发布时间】:2017-02-08 10:34:17
【问题描述】:

我一直在查看不同的CQRS samples,其中大多数使用不保存UnitOfWork 的命令处理程序(即DataContext,以防Entity Framework)。像这样的:

    public void Handle(Command message)
    {
        var course = Mapper.Map<Command, Course>(message);

        _db.Courses.Add(course);
    }

保存(和事务提交)通常在处理请求时在后台进行。

我从许多领先的 CQRS 专家那里看到了这种方法,但我从未听说过它的原因。

这种方法的最大问题是当您需要在处理程序调用返回后立即获取实体 ID(这种情况经常发生)。显然有一些方法可以解决它(即使用 Guid、从数据库中预先请求唯一 ID 等)但看起来很笨拙。

但是这种方法的优点是什么?从理论上讲,如果我们每个请求有多个处理程序,则不进行多次数据库往返可能会有所帮助。但它不会发生很多。我想到的另一个优点是我们不必键入例行的 Save 调用并让它自动发生。这有点好,但它是否加重了 ID 生成问题?

【问题讨论】:

    标签: .net cqrs mediatr


    【解决方案1】:

    为什么 CQRS 命令处理程序不包括保存 UnitOfWork?

    我认为它始于 Evans,Domain Driven Design,第 6 章 域对象的生命周期

    有很多技术可以应对数据库访问的技术挑战......

    但即便如此,请注意丢失的内容。我们不再考虑领域模型中的概念。我们的代码不会与业务相关,它会操纵数据检索技术。

    我们的想法是,在代码的这一点上,我们正在使用 域模型,而不是查看 数据模型

    存储库减轻了客户端的巨大负担,它现在可以与一个简单的、意图揭示的界面对话,并根据模型询问它需要什么

    埃文斯在交易方面非常强调这一点

    将事务控制权交给客户端。虽然 REPOSITORY 会插入和删除数据库,但它通常不会提交任何内容。例如,在保存后提交是很诱人的,但客户端可能具有正确启动和提交工作单元的上下文。如果 REPOSITORY 不干预,事务管理会更简单。

    一些补充说明:

    这种方法的最大问题是当您需要在处理程序调用返回后立即获取实体 ID(这种情况经常发生)。

    这通常表明您正在解决错误的问题。请参阅 Marc de Graauw,Nobody Needs Reliable Messaging

    【讨论】:

    • 我觉得使用存储库更有意义。当我们直接使用 DataContext 时,我们不使用域,我们修改数据存储。然后我们不进行最后一步(保存我们修改的内容)并假装我们将域对象操作与数据存储分离。
    【解决方案2】:

    命令处理程序的一个重要特性是它不返回任何内容(异常除外)。这是一个微妙的点,但如果您知道所有命令处理程序都不会返回任何内容,那么您可以节省大量代码并简化或创建更健壮的代码库。

    但是,如果您没有返回任何内容,那么您会遇到在进程开始时需要 id 的情况。我认为使用 GUID 是一个优雅的解决方案。

    从数据库中预取唯一 ID 充满了问题,如果可能,我会避免这种方法。

    这里有一些优点:

    1. 所有命令处理程序都有一个通用接口
    2. 因此,您可以编写支持所有命令处理程序的帮助代码。例如命令路由器、安全和权限检查、日志记录、性能监控、消息队列......
    3. 它可以显着减少您需要编写的代码量
    4. 它可以显着降低您需要编写的代码的复杂度
    5. 测试更简单、更可靠

    这些只是我脑海中的一些。

    为什么不包括一个工作单元?

    你可以是简短的回答。但我喜欢将持久性的责任从处理程序中移出。处理程序可能会调用它,但实际的持久性是在其他地方完成的(在大多数情况下,我的偏好是在事件存储中)。

    【讨论】:

    • 感谢您的回答,但我不会称 Guids 优雅 :)
    • 为什么不呢?创建一个独立于数据库的全局唯一 ID。我觉得这很酷。
    • 嗯...它们很丑 :) 如果你需要在 url 中显示基于 Guid 的 id,它永远不会感觉正确
    • 哦,是的 - 在 url 中它们看起来很糟糕。但像往常一样,这取决于上下文。内部应用程序,业务可能不在乎。外部 SEO 友好的网站,然后我不会显示它们(但总有一个简单的解决方法)。
    • 顺便问一下,有什么简单的解决方法?没听说过。
    猜你喜欢
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多