Model view controller 什么';查询DTO投影的正确位置是哪里?

Model view controller 什么';查询DTO投影的正确位置是哪里?,model-view-controller,domain-driven-design,dto,Model View Controller,Domain Driven Design,Dto,出于不同的原因(关注点分离、性能),我希望停止向视图发送域实体,而是使用DTO投影 我想使用ORM查询来创建DTO,只从一个或多个实体中选择所需的字段 正确的地点是哪里? 答:没有 控制器:我希望使它们尽可能薄,并避免让它们执行查询和/或映射 我觉得应该有一个集中的地方(类似于实体的存储库)来查询和创建DTO,但我没有找到这种做法的模式或命名 我遇到过这个术语,但它看起来像是用于将一个或多个域实体映射到DTO,而在我的例子中,我希望跳过加载完整实体,直接将数据库查询转换为DTO 这有一种模式

出于不同的原因(关注点分离、性能),我希望停止向视图发送域实体,而是使用DTO投影

我想使用ORM查询来创建DTO,只从一个或多个实体中选择所需的字段

正确的地点是哪里?

  • 答:没有
  • 控制器:我希望使它们尽可能薄,并避免让它们执行查询和/或映射
我觉得应该有一个集中的地方(类似于实体的存储库)来查询和创建DTO,但我没有找到这种做法的模式或命名

我遇到过这个术语,但它看起来像是用于将一个或多个域实体映射到DTO,而在我的例子中,我希望跳过加载完整实体,直接将数据库查询转换为DTO

这有一种模式吗?

您的DTO代表一种读取模式。为此,我通常使用一个查询“层”(尽管我倾向于更多地考虑关注点而不是层)。我通常使用
I{Aggregate}查询
,使用方式与使用
I{Aggregate}存储库
相同

接口将以尽可能简单的格式返回数据:

namespace Company.Project.DataAccess
{
    public interface ICustomerQuery
    {
        int CountMatching(Query.Customer.Specification specification);
        int Count();
        IEnumerable<DataRow> RowsMatching(Query.Customer.Specification specification); // perhaps OK for simple cases
        IEnumerable<Query.Customer> Matching(Query.Customer.Specification specification); // for something more complex
    }
}   
您的DTO代表一个读取模型。为此,我通常使用一个查询“层”(尽管我倾向于更多地考虑关注点而不是层)。我通常使用
I{Aggregate}查询
,使用方式与使用
I{Aggregate}存储库
相同

接口将以尽可能简单的格式返回数据:

namespace Company.Project.DataAccess
{
    public interface ICustomerQuery
    {
        int CountMatching(Query.Customer.Specification specification);
        int Count();
        IEnumerable<DataRow> RowsMatching(Query.Customer.Specification specification); // perhaps OK for simple cases
        IEnumerable<Query.Customer> Matching(Query.Customer.Specification specification); // for something more complex
    }
}   

dto是应用层的对象。您想要的是直接从数据库填充它。它是cqrs的查询端,您没有像命令端那样的丰富域模型,只有适合客户端的投影(dto)。它们是查询(读取)模型

更新:

这些是我使用的模式的对象,类似于命令,但查询有一个结果:

public interface QueryResult {}
普通DTO(或它们的列表),带有客户端的输出数据

public interface Query<QR extends QueryResult> {}
公共接口查询{}
带有输入数据(搜索条件)的普通DTO,用于执行查询

public interface QueryHandler <QR extends QueryResult, Q extends Query<QR>> {
    public QR handle ( Q query );
}
公共接口查询处理器{
公共QR句柄(Q查询);
}
执行查询的对象

public interface QueryHandler <QR extends QueryResult, Q extends Query<QR>> {
    public QR handle ( Q query );
}
示例:

  • 管理公司员工、部门等数据的应用程序
  • 用例:给我一份30岁以下、工资超过2000欧元的员工名单(仅包括姓名、电子邮件、离职、工资)
代码:

class EmployeeDto{
私有字符串名称;
私人字符串电子邮件;
私有字符串departmentName;
私人双薪;
...
...
}
类EmployeeDtoList实现QueryResult{
私人名单雇员人数;
...
...
}
类EmployeesBageAndSalary实现查询{
私人日历最大年龄;
私人双敏沙拉;
...
...
}
类EmployeesBageAndSalaryHandler实现QueryHandler{
...
@凌驾
公共EmployeeDtoList句柄(EmployeesBageAndAlary查询){
...
...
}
}
-- 客户端使用的facade是一个中介(与此方法的接口):

公共QR执行(Q查询);
中介器将由管理查询处理程序注册表的类实现,以便它将请求重定向到与给定查询关联的查询处理程序


它类似于命令模式,但带有查询。

dto是应用层的对象。您想要的是直接从数据库填充它。它是cqrs的查询端,您没有像命令端那样的丰富域模型,只有适合客户端的投影(dto)。它们是查询(读取)模型

更新:

这些是我使用的模式的对象,类似于命令,但查询有一个结果:

public interface QueryResult {}
普通DTO(或它们的列表),带有客户端的输出数据

public interface Query<QR extends QueryResult> {}
公共接口查询{}
带有输入数据(搜索条件)的普通DTO,用于执行查询

public interface QueryHandler <QR extends QueryResult, Q extends Query<QR>> {
    public QR handle ( Q query );
}
公共接口查询处理器{
公共QR句柄(Q查询);
}
执行查询的对象

public interface QueryHandler <QR extends QueryResult, Q extends Query<QR>> {
    public QR handle ( Q query );
}
示例:

  • 管理公司员工、部门等数据的应用程序
  • 用例:给我一份30岁以下、工资超过2000欧元的员工名单(仅包括姓名、电子邮件、离职、工资)
代码:

class EmployeeDto{
私有字符串名称;
私人字符串电子邮件;
私有字符串departmentName;
私人双薪;
...
...
}
类EmployeeDtoList实现QueryResult{
私人名单雇员人数;
...
...
}
类EmployeesBageAndSalary实现查询{
私人日历最大年龄;
私人双敏沙拉;
...
...
}
类EmployeesBageAndSalaryHandler实现QueryHandler{
...
@凌驾
公共EmployeeDtoList句柄(EmployeesBageAndAlary查询){
...
...
}
}
-- 客户端使用的facade是一个中介(与此方法的接口):

公共QR执行(Q查询);
中介器将由管理查询处理程序注册表的类实现,以便它将请求重定向到与给定查询关联的查询处理程序


它类似于命令模式,但有查询。

这是一个很好的问题

您可以将它们放在应用程序层中。您寻找的模式称为查询服务

看看Vaughn Vernon(实现域驱动设计的作者)在其github repo中的表现:

然后,他直接从查询服务(CQRS)中的DB填充它们