数据传输对象(通常称为DTO)通常是POCO(普通旧CLR对象)类的实例,用作容器来封装数据并将其从应用程序的一层传递到另一层。 通常,您会发现服务层中正在使用DTO将数据返回到表示层。 使用DTO的最大优点是将客户端与内部数据结构分离。
本文讨论了为什么我们应该使用数据传输对象以及如何在ASP.NET Core 3.1中使用它们。 若要使用本文提供的代码示例,您应该在系统中安装Visual Studio 2019。 如果您还没有副本,则可以在此处下载Visual Studio 2019 。
[ 也在InfoWorld上:隔离期间最好的免费数据科学课程 ]
创建一个ASP.NET Core 3.1 API项目
首先,让我们在Visual Studio中创建一个ASP.NET Core项目。 假设系统中已安装Visual Studio 2019,请按照以下概述的步骤在Visual Studio中创建一个新的ASP.NET Core API项目。
- 启动Visual Studio IDE。
- 点击“创建新项目”。
- 在“创建新项目”窗口中,从显示的模板列表中选择“ ASP.NET Core Web应用程序”。
- 点击下一步。
- 在“配置新项目”窗口中,指定新项目的名称和位置。
- 单击创建。
- 在接下来显示的“创建新的ASP.NET Core Web应用程序”窗口中,从顶部的下拉列表中选择.NET Core作为运行时,并选择ASP.NET Core 3.1(或更高版本)。
- 选择“ API”作为项目模板以创建新的ASP.NET Core API应用程序。
- 确保未选中“启用Docker支持”和“配置HTTPS”复选框,因为我们此处将不使用这些功能。
- 确保将身份验证设置为“无身份验证”,因为我们也不会使用身份验证。
- 单击创建。
这将在Visual Studio中创建一个新的ASP.NET Core API项目。 在本文的后续部分中,我们将使用该项目来处理数据传输对象。
为什么要使用数据传输对象(DTO)?
在设计和开发应用程序时,如果您使用模型在各层之间传递数据并将数据发送回表示层,那么您将公开应用程序的内部数据结构。 那是您应用程序中的主要设计缺陷。
通过分离各层,DTO使您在实现API,MVC应用程序以及诸如Message Broker之类的消息传递模式时更加轻松。 当您想通过导线传递轻型物体时,DTO是一个不错的选择,尤其是当您通过带宽受限的介质传递物体时。
使用DTO进行抽象
您可以利用DTO从用户界面或表示层抽象应用程序的域对象。 这样,应用程序的表示层便与服务层分离了。 因此,如果您想更改表示层,则可以轻松完成此操作,而应用程序将继续与现有域层一起使用。 同样,您可以更改应用程序的域层,而不必更改应用程序的表示层。
使用DTO进行数据隐藏
您想要使用DTO的另一个原因是数据隐藏。 也就是说,通过使用DTO,您只能返回请求的数据。 例如,假设您有一个名为GetAllEmployees()的方法,该方法返回与所有雇员有关的所有数据。 让我们通过编写一些代码来说明这一点。
在我们之前创建的项目中,创建一个名为Employee.cs的新文件。 在此文件中编写以下代码,以定义名为Employee的模型类。
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string DepartmentName { get; set; }
public decimal Basic { get; set; }
public decimal DA { get; set; }
public decimal HRA { get; set; }
public decimal NetSalary { get; set; }
}
请注意,Employee类包含的属性包括Id,FirstName,LastName,Department,Basic,DA,HRA和NetSalary。 但是,表示层可能只需要GetAllEmployees()方法中员工的Id,FirstName,LastName和Department Name。 如果此方法返回List <Employee>,则任何人都可以看到该员工的薪水详细信息。 你不要那样
为避免此问题,您可以设计一个名为EmployeeDTO的DTO类,该类仅包含所请求的属性(例如Id,FirstName,LastName和Department Name)。
在C#中创建DTO类
为此,请创建一个名为EmployeeDTO.cs的文件,并在其中编写以下代码。
public class EmployeeDTO
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string DepartmentName { get; set; }
}
现在可以使用模型和数据传输对象类,您可能想要创建一个包含两个方法的转换器类:一个将Employee模型类的实例转换为EmployeeDTO的实例,(反之亦然)一个将实例转换为EmployeeDTO的实例。 EmployeeDTO到Employee模型类的实例。 您还可以利用AutoMapper(一种流行的对象到对象映射库)来映射这两种不同的类型。 您可以在此处阅读有关AutoMapper的更多信息 。
您应该在应用程序的服务层中创建List <EmployeeDTO>,并将集合返回到表示层。
DTO的不变性
DTO旨在将数据从应用程序的一层传输到另一层。 DTO的使用者可以用.NET / C#/ Java甚至JavaScript / TypeScript构建。 DTO通常是序列化的,因此它可以独立于接收器中使用的技术。 在大多数情况下,数据的接收者不需要在收到后修改该数据,理想情况下不需要!
这是不变性重要性的经典示例。 这就是为什么DTO应该是不变的!
您可以通过多种方式在C#中实现不可变DTO。 您可以使用ReadOnlyCollection或System.Collections.Immutable命名空间中存在的线程安全的不可变集合类型。 您还可以利用C#9中的记录类型来实现不可变的DTO。
域驱动的设计期望域对象在外部是不可变的。 这是使您的DTO不可变的一个很好的理由,不是吗?
DTO序列化挑战
您应该能够无缝地对DTO进行序列化/反序列化,以便可以将DTO向下传递。 但是,实际上,在使用DTO时,您可能必须解决一些序列化问题。 在实际应用程序中,您可能有多个实体或模型类,并且每个实体或模型类可能相互引用。
假设您已经为组织中的员工构建了考勤管理系统。 通常,您的应用程序中可能有一个名为Employee的类,它引用User类(即Employee是应用程序的用户),而该类又引用了Role类。 角色类可能引用Permission类,而后者又可能引用PermissionType和PermissionGroup类。 现在,当序列化Employee类的实例时,您还将最终序列化这些对象。 很容易看到,在某些复杂的情况下,您可能最终会序列化几种类型。
在这里可以轻松进行惰性加载或异步加载。 此功能可以帮助您仅在需要时才加载实体。 有关如何执行延迟加载的更多信息,请查看我有关C#中的延迟初始化的文章。
数据传输对象通常不包含任何业务逻辑-它们仅包含数据。 在使用DTO时,不变性是一个理想的功能。 有几种方法可以实现不可变的DTO。 我将在后面的文章中讨论C#中的不变性。
如何在ASP.NET Core中执行更多操作:
- 如何处理ASP.NET Core MVC中的404错误
- 如何在ASP.NET Core 3.1的操作筛选器中使用依赖项注入
- 如何在ASP.NET Core中使用选项模式
- 如何在ASP.NET Core 3.0 MVC中使用终结点路由
- 如何在ASP.NET Core 3.0中将数据导出到Excel
- 如何在ASP.NET Core 3.0中使用LoggerMessage
- 如何在ASP.NET Core中发送电子邮件
- 如何在ASP.NET Core中将数据记录到SQL Server
- 如何在ASP.NET Core中使用Quartz.NET安排作业
- 如何从ASP.NET Core Web API返回数据
- 如何在ASP.NET Core中格式化响应数据
- 如何使用RestSharp使用ASP.NET Core Web API
- 如何使用Dapper执行异步操作
- 如何在ASP.NET Core中使用功能标志
- 如何在ASP.NET Core中使用FromServices属性
- 如何在ASP.NET Core中使用Cookie
- 如何在ASP.NET Core中使用静态文件
- 如何在ASP.NET Core中使用URL重写中间件
- 如何在ASP.NET Core中实施速率限制
- 如何在ASP.NET Core中使用Azure应用程序见解
- 在ASP.NET Core中使用高级NLog功能
- 如何处理ASP.NET Web API中的错误
- 如何在ASP.NET Core MVC中实现全局异常处理
- 如何在ASP.NET Core MVC中处理空值
- ASP.NET Core Web API中的高级版本控制
- 如何在ASP.NET Core中使用辅助服务
- 如何在ASP.NET Core中使用Data Protection API
- 如何在ASP.NET Core中使用条件中间件
- 如何在ASP.NET Core中使用会话状态
- 如何在ASP.NET Core中编写高效的控制器
翻译自: https://www.infoworld.com/article/3562271/how-to-use-data-transfer-objects-in-aspnet-core-31.html