在CQRS中,我的阅读方应该返回DTO还是ViewModels?

Jos*_*off 31 c# cqrs

我正在与我的同事就CQRS应用程序的读取方面进行辩论.

选项1:我的CQRS应用程序的应用程序读取端返回DTO,例如:

public interface IOrderReadService
{
    public OrderDto Load(int id);
}

public class SomeController
{
    public ActionResult SomeAction(int id)
    {
        var dto = ObjectFactory.GetInstance<IOrderReadService>().Load(id);
        var viewModel = Mapper.Map<OrderDto, SomeViewModel>();
        return View(viewModel);
    }
}

public class SomeOtherController
{
    public ActionResult SomeOtherAction(int id)
    {
        var dto = ObjectFactory.GetInstance<IOrderReadService>().Load(id);
        var viewModel = Mapper.Map<OrderDto, SomeOtherViewModel>();
        return View(viewModel);
    }
}
Run Code Online (Sandbox Code Playgroud)

选项2:应用程序读取端返回ViewModels,例如:

public interface IOrderReadService
{
    public SomeViewModel LoadSomething(int id);
    public SomeOtherViewModel LoadSomethingElse(int id);
}

public class SomeController
{
    public ActionResult SomeAction(int id)
    {
        return View(ObjectFactory.GetInstance<IOrderReadService>().LoadSomething(id));
    }
}

public class SomeOtherController
{
    public ActionResult SomeOtherAction(int id)
    {
        return View(ObjectFactory.GetInstance<IOrderReadService>().LoadSomethingElse(id));
    }
}
Run Code Online (Sandbox Code Playgroud)

从我的同事和我在这件事上所做的研究来看,反应看起来好坏参半 - 看起来它真的取决于背景.所以我问你,亲爱的StackOverflowians:

一种方法似乎比另一种方法有明显的优势吗?如果是这样,他们是什么?

Den*_*aub 30

一般建议是每个屏幕一个投影(格雷格杨)或每个小部件一个投影(如果我正确理解Udi Dahan).

要将读取模型合并到DTO中,再次必须将其映射到单独的视图中,这与优化的读取模型的整个目的相矛盾.它增加了我们试图摆脱的复杂性和映射步骤.

我的建议:SELECT * FROM ViewSpecificTable [WHERE ...]如果在瘦读取层中使用NoSQL,请尝试尽可能接近或类似.

Aggregate Roots及其"子"的概念在读取方面没有太多含义,因为这些是域模型概念.您不希望在读取端具有域模型,它只存在于写入端.

Mohamed Abed提到的特定于UI平台的转换应该在UI层中完成,而不是在读取模型本身中完成.

简而言之:我选择选项2.为了不将它与特定于平台的东西混淆ViewModel,我宁可称之为ReadModel但每个视图都有一个.


Udi*_*han 13

DDD/CQRS的主要原则之一是您不应该编辑视图模型.相反,基于任务的屏幕应引导用户发出显式命令.如果你不能提出基于任务的屏幕,你应该使用不同形式的CQRS,就像我在这里描述的那样:

http://udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere/


Moh*_*bed 6

我更愿意返回DTO将应用程序层与表示技术分开(因为每种表示技术可能对表示模型的结构有一些要求),例如,Web MVC应用程序绑定与WPF MVVM绑定不同,您也可能需要一些属性视图模型中的/ fields与应用程序数据无关,例如(SliderWidth或IsEmailFieldEnabled,...).另外,例如,如果使用WPF MVVM,我需要实现INotifyPropertyChanged接口以允许绑定,在应用程序读取服务中实现此接口不方便也无关联.

所以我更希望将读取数据表示的关注与实际的表示技术和视图模型分开.

所以选项1对我来说更好

  • 在CQRS中,不应该使用视图模型来更改数据.而应发送显式命令. (2认同)
  • 是的,我已经只在谈论只读模型,也许我误解了示例(滑块),但是我的意思是(进度条)或绑定为只读视图的任何只读属性 (2认同)