【问题标题】:Using the Command-Query Separation principle in MVC Controllers在 MVC 控制器中使用命令-查询分离原则
【发布时间】:2012-05-03 23:22:27
【问题描述】:

我喜欢Command Query Separation 的想法,但看不到如何在添加实体的 MVC 控制器操作中使用它,并且在添加后需要新实体的 ID。

例如,在下面的简化示例中,服务用于创建新项目:

public ActionResult Assign(AssignViewModel viewModel)
{
     var newItem = _AssignItemService.AssignItem(viewModel.ItemName, viewModel.ItemValue);

     return RedirectToAction("ListItem", new {id = newItem.Id);
}

但是当我重定向到要显示新项目的操作时,我需要知道新创建的项目的 ID,以便可以从数据库中检索它。所以我必须要求服务返回新创建的项目(或至少,它的 ID)。

在纯 CQS 中,命令没有返回值,所以上面的模式是无效的。

感谢您的任何建议。

【问题讨论】:

    标签: c# asp.net-mvc command-query-separation


    【解决方案1】:

    我认为你陷入了迂腐的境地。

    查询是当您想向数据库询问一个问题时,例如“密西西比河以西有多少客户在 6 月份购买了红色商品?” 这是一个查询。在插入期间返回 ID 本身并不是一个典型的查询。

    与软件开发中的大多数其他事情一样,这种模式并不是绝对的甚至 Fowler 也表示他愿意在方便时打破它:

    弹出堆栈是修改状态的修饰符的一个很好的例子。 迈耶正确地说你可以避免使用这种方法,但它是 一个有用的成语。所以我宁愿尽可能遵循这个原则,但是 我准备打破它以获得我的流行音乐。

    如果你真的想从数据库中检索最近添加的 ID,而不是插入它,你可以使用类似 Scope Identity 的东西。但我认为你在增加复杂性并没有额外的好处。

    【讨论】:

    • 另外,请确保如果您使用 Scope 标识或类似标识,您可以正确处理多线程情况。例如,T1 插入,T2 插入,T1T2s 插入中获取 IdT2 获取相同的 Id。当然,同样的问题适用于任何原子操作/事务,所以我相信你已经考虑过了。
    • 另一个很好的理由让数据库通过插入函数的返回值将 ID 交给你。
    • 我认为 Fowler 的评论考虑到堆栈中的 pop 方法是可以的,因为它的用途很普遍,因此它已成为所有开发人员的习惯用法,但我不认为从save 方法是一个成语。我同意你的观点,虽然没有什么是绝对的,偶尔打破这种规则也没什么大不了
    • @jorgehmv:这将是一个插入方法,从数据库中返回一个 ID 是一个非常常见且很好理解的习语。
    • @Robert ok 也许是这样,但多年前从方法返回错误代码也是一个很好理解的习惯用法,这不再是一个好习惯了,martinfowler.com/refactoring/catalog/…
    【解决方案2】:

    您应该将根据视图模型的值创建的“Item”(或任何您的实体名称)的实例传递给AssignItem 方法,然后该方法不必返回任何内容,而只会更新实体的 Id 属性使其成为命令方法。

    然后您可以将 entity.Id 用于您想要的任何内容

    【讨论】:

    • 以后如何检索“item”?
    • 传递给AssignItem方法的对象一旦返回就包含了Id信息。由于该方法是一个命令,因此可以更改对象的状态
    • 那时你基本上不是还在返回一个值吗?当然,它不是从函数的后面出来的,但你仍然返回一个值,你只是将返回值推到其他地方。也就是说,我喜欢将 ID 保留在对象中的想法,而不是单独返回它。
    • 这种差异是大多数时候命令查询分离是个好主意的主要原因。如果您使用相同的参数多次调用相同的方法,它每次都会返回不同的东西,这很奇怪。相反,如果你一次又一次地传递同一个对象,它总是不会返回任何内容,并且只会在必要时更改对象的状态(通常只是因为那是数据库插入后的第一次)
    • 你永远不会传递同一个对象进行两次插入。该方法每次返回不同的东西是设计使然;每个新 ID 都必须是唯一的,才能将其与其他 ID 区分开来。
    【解决方案3】:

    这样做的方法是让调用者指定新实体的 ID(这很可能意味着使用 GUID 作为键)。

    但是,根据我的经验,强加命令可能不会返回结果的(纯粹的)规则将导致问题收效甚微。

    【讨论】:

    • 感谢 erikkallen。有道理,但最后我认为 jorgehmv 的想法对我来说会更好。
    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2014-06-21
    相关资源
    最近更新 更多