经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » SQL语言 » 查看文章
武装你的WEBAPI-OData与DTO
来源:cnblogs  作者:波多尔斯基  时间:2023/5/8 10:21:22  对本文有异议

本文属于OData系列文章

Intro

前面写了很多有关OData使用的文章,很多读者会有疑问,直接将实体对象暴露给最终用户会不会有风险?$expand在默认配置的情况下,数据会不会有泄露风险?

答案是肯定的,由于OData的特性,提供给我们便捷同时也会带来一些风险。很多地方推荐使用DTO模式来隔离实体类与最终用户使用到类的关系,从而解决以上两个问题,OData同样也适用。

DTO

DTO代表Data Transfer Object,是一种设计模式,用于在不同层之间传输数据。它通常用于将数据从一个应用程序的逻辑层传输到另一个应用程序的界面层或持久化层,以及在分布式系统中传输数据。

DTO对象是纯数据对象,它包含要从一个应用程序传输到另一个应用程序的数据。它不包含业务逻辑或数据访问代码,因此它们不能直接与数据库交互或执行任何操作,而只是简单地保存数据。

DTO对象通常由开发人员创建,并且可以根据需要进行扩展。它们可以包含各种属性和方法,以提供使用方便和更好的可读性。使用DTO对象可以降低耦合度,使不同层之间的数据传输更加简单和安全。

AutoMapper

我们需要将实体对象与DTO进行转换,对于需要转换数量不是很多的情况,直接编写一个转换函数就方便了。

  1. public static class DeviceDataExtension
  2. {
  3. public static DeviceDataDto ToDeviceDataDto(this Datum deviceData)
  4. {
  5. if (deviceData == null) return null;
  6. DeviceDataDto deviceDataDto = new()
  7. {
  8. DataArray = deviceData.DataArray,
  9. DeviceId = deviceData.DeviceId,
  10. Timestamp = deviceData.Timestamp,
  11. Id = Guid.NewGuid().ToString()
  12. };
  13. return deviceDataDto;
  14. }
  15. }

但是如果需要映射的属性很多,或者有很多对象的情况,建议使用对象映射工具:AutoMapper。基础用法不详细说了,讲讲对OData的支持。

首先安装对OData支持的包,由于我使用默认的DI,还需要安装DI支持的包:

  1. Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
  2. Install-Package AutoMapper.AspNetCore.OData.EFCore

然后有三个要求:

  • 一定要对对象声明显示展开(explicit expansion)。
  • 调用IMapper的GetAsync()或者GetQueryAsync()方法。
  • 不能在Controller或者方法上使用[EnableQuery]特性:这个我熟,因为GetQueryAsync()函数需要利用ODataQueryOptions参数,如果同时使用[EnableQuery]会导致对结果再进行一次筛选,导致返回数据错误。

代码:

  1. services.AddAutoMapper(option =>
  2. {
  3. option.CreateMap<Datum, DeviceDataDto>()
  4. .ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid().ToString()))
  5. .ForPath(dest => dest.DataArray, opt => opt.MapFrom(src => src.DataArray))
  6. .ForAllMembers(w => w.ExplicitExpansion());
  7. });
  1. public DeviceDatasController(IMapper mapper)
  2. {
  3. _mapper = mapper;
  4. }
  5. [HttpGet]
  6. [ProducesResponseType(typeof(IEnumerable<DeviceDataDto>), Status200OK)]
  7. public async Task<IActionResult> GetAsync(string key, ODataQueryOptions<DeviceDataDto> options)
  8. {
  9. var insp = await _context.DeviceData.Where(w => w.DeviceId == key).GetQueryAsync(_mapper, options);
  10. return Ok(insp);
  11. }

这样,我们就可以正常使用 OData,同时也享受了的 DTO 的好处,即可以对 DeviceDataDto 使用的 OData 查询。使用的时候要注意,如果有导航属性,导航属性也需要配置映射。

参考资料

原文链接:https://www.cnblogs.com/podolski/p/17380728.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号