Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在CQRS中,我的读取端应该返回DTO还是VIEWMODEL?_C#_Cqrs - Fatal编程技术网

C# 在CQRS中,我的读取端应该返回DTO还是VIEWMODEL?

C# 在CQRS中,我的读取端应该返回DTO还是VIEWMODEL?,c#,cqrs,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.GetI

我正在与我的同事就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);
    }
}
公共接口IORDReadService
{
要加载的公共命令(int id);
}
公共类控制器
{
public ActionResult SomeAction(int-id)
{
var dto=ObjectFactory.GetInstance().Load(id);
var viewModel=Mapper.Map();
返回视图(viewModel);
}
}
公共类SomeOtherController
{
公共操作结果SomeOtherAction(int id)
{
var dto=ObjectFactory.GetInstance().Load(id);
var viewModel=Mapper.Map();
返回视图(viewModel);
}
}
选项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));
    }
}
公共接口IORDReadService
{
public SomeViewModel LoadSomething(int-id);
public someotherview模型LoadSomethingElse(int-id);
}
公共类控制器
{
public ActionResult SomeAction(int-id)
{
返回视图(ObjectFactory.GetInstance().LoadSomething(id));
}
}
公共类SomeOtherController
{
公共操作结果SomeOtherAction(int id)
{
返回视图(ObjectFactory.GetInstance().LoadSomethingElse(id));
}
}
从我的同事和我对这件事所做的研究来看,反应似乎是喜忧参半——这看起来真的取决于上下文。所以我问你们,我亲爱的斯塔克沃夫人:


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

读模型是写模型的投影。它的存在是为了实现一个特定的目的。在您的情况下,这似乎为MVC控制器提供了视图模型。因此,为什么要麻烦地将DTO映射到Viewmodels?我能想到的唯一原因是,拥有两个独立的读取模型的好处可能不会超过它们的维护成本。但是,要考虑到“合并”读取“重用”和“降低维护成本”的模型会增加开发人员的复杂性(我能改变这个表吗?嗯,我现在有两个(或更多)的消费者我必须考虑到-有点像数据库整合一样)。
只是我的想法。

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

因此,我更愿意将读取数据表示与实际的表示技术和视图模型分离开来


因此,选项1更适合我

一般建议是每个屏幕投影一次(Greg Young),或者甚至每个小部件投影一次(如果我正确理解Udi Dahan)

将读取模型整合到DTO中,而DTO又必须映射到单独的视图中,这与优化读取模型的整体目的相矛盾。它增加了我们最初试图摆脱的复杂性和映射步骤

我的建议是:如果在精简阅读层中使用NoSQL,请尽量靠近
SELECT*fromViewSpecificTable[WHERE…]
或类似的内容

聚合根及其“子项”的概念在阅读端没有太多的含义,因为它们是领域模型概念。您不希望在读端拥有域模型,它只存在于写端

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


长话短说:我会选择选项2。为了不将其与特定于平台的视图模型混淆,我宁愿将其称为
ReadModel
,但每个视图都有一个视图。

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


我应该补充一点,主要的分歧点在于编辑屏幕处理的是聚合根的孩子。无耻地提到我自己:你的问题让我想到了返回ViewModels的后果。谢谢你今天的食物!在CQRS中,不应使用视图模型来更改数据。相反,应该发送明确的命令。是的,我已经在谈论只读模型,可能我错误地描述了示例(滑块),但我的意思是(progressbar)或任何要绑定到只读视图的只读属性投影很难做到,因为我们只有一个,首先使用EF代码完成的关系数据存储。我不知道如何在上面创建视图。我是否正确理解您:您想从您在写端使用的EF模型中提取DTO/ViewModels?听起来好像只是通过从单个模型映射数据来人为地分离读写模型。在这种情况下,使用DTO和ViewModels之间没有太大区别,因为您正在失去读/写分离的固有好处。[附录:]在CQRS中,您不希望将视图置于EF模型之上(或者至少这只是转换遗留代码的第一步)。您可能希望直接从数据库构建视图。不管是NoSQL,separa