本文屬于OData系列文章
Intro
前面寫了很多有關(guān)OData使用的文章,很多讀者會有疑問,直接將實體對象暴露給最終用戶會不會有風(fēng)險?$expand在默認(rèn)配置的情況下,數(shù)據(jù)會不會有泄露風(fēng)險?
答案是肯定的,由于OData的特性,提供給我們便捷同時也會帶來一些風(fēng)險。很多地方推薦使用DTO模式來隔離實體類與最終用戶使用到類的關(guān)系,從而解決以上兩個問題,OData同樣也適用。
DTO
DTO代表Data Transfer Object
,是一種設(shè)計模式,用于在不同層之間傳輸數(shù)據(jù)。它通常用于將數(shù)據(jù)從一個應(yīng)用程序的邏輯層傳輸?shù)搅硪粋€應(yīng)用程序的界面層或持久化層,以及在分布式系統(tǒng)中傳輸數(shù)據(jù)。
DTO對象是純數(shù)據(jù)對象,它包含要從一個應(yīng)用程序傳輸?shù)搅硪粋€應(yīng)用程序的數(shù)據(jù)。它不包含業(yè)務(wù)邏輯或數(shù)據(jù)訪問代碼,因此它們不能直接與數(shù)據(jù)庫交互或執(zhí)行任何操作,而只是簡單地保存數(shù)據(jù)。
DTO對象通常由開發(fā)人員創(chuàng)建,并且可以根據(jù)需要進(jìn)行擴(kuò)展。它們可以包含各種屬性和方法,以提供使用方便和更好的可讀性。使用DTO對象可以降低耦合度,使不同層之間的數(shù)據(jù)傳輸更加簡單和安全。
AutoMapper
我們需要將實體對象與DTO進(jìn)行轉(zhuǎn)換,對于需要轉(zhuǎn)換數(shù)量不是很多的情況,直接編寫一個轉(zhuǎn)換函數(shù)就方便了。
public static class DeviceDataExtension
{
public static DeviceDataDto ToDeviceDataDto(this Datum deviceData)
{
if (deviceData == null) return null;
DeviceDataDto deviceDataDto = new()
{
DataArray = deviceData.DataArray,
DeviceId = deviceData.DeviceId,
Timestamp = deviceData.Timestamp,
Id = Guid.NewGuid().ToString()
};
return deviceDataDto;
}
}
但是如果需要映射的屬性很多,或者有很多對象的情況,建議使用對象映射工具:AutoMapper
?;A(chǔ)用法不詳細(xì)說了,講講對OData的支持。
首先安裝對OData支持的包,由于我使用默認(rèn)的DI,還需要安裝DI支持的包:
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
Install-Package AutoMapper.AspNetCore.OData.EFCore
然后有三個要求:
- 一定要對對象聲明顯示展開(explicit expansion)。
- 調(diào)用IMapper的
GetAsync()
或者GetQueryAsync()
方法。 - 不能在Controller或者方法上使用[EnableQuery]特性:這個我熟,因為
GetQueryAsync()
函數(shù)需要利用ODataQueryOptions
參數(shù),如果同時使用[EnableQuery]
會導(dǎo)致對結(jié)果再進(jìn)行一次篩選,導(dǎo)致返回數(shù)據(jù)錯誤。
代碼:文章來源:http://www.zghlxwxcb.cn/news/detail-436285.html
services.AddAutoMapper(option =>
{
option.CreateMap<Datum, DeviceDataDto>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.NewGuid().ToString()))
.ForPath(dest => dest.DataArray, opt => opt.MapFrom(src => src.DataArray))
.ForAllMembers(w => w.ExplicitExpansion());
});
public DeviceDatasController(IMapper mapper)
{
_mapper = mapper;
}
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<DeviceDataDto>), Status200OK)]
public async Task<IActionResult> GetAsync(string key, ODataQueryOptions<DeviceDataDto> options)
{
var insp = await _context.DeviceData.Where(w => w.DeviceId == key).GetQueryAsync(_mapper, options);
return Ok(insp);
}
這樣,我們就可以正常使用 OData,同時也享受了的 DTO 的好處,即可以對 DeviceDataDto 使用的 OData 查詢。使用的時候要注意,如果有導(dǎo)航屬性,導(dǎo)航屬性也需要配置映射。文章來源地址http://www.zghlxwxcb.cn/news/detail-436285.html
參考資料
- AutoMapper/AutoMapper.Extensions.OData: Creates LINQ expressions from ODataQueryOptions and executes the query. (github.com)
到了這里,關(guān)于武裝你的WEBAPI-OData與DTO的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!