(精華)2020年8月22日 ABP vNext DTO在應用層的使用
我們繼續應用層的開發,首先建立負責在應用層和展示層之間傳遞資料的物件,也就是DTO。
使用DTO的原因
為什麼需要DTO呢?有如下幾個原因。
- 隔離領域層與表示層,使領域層和表示層可以獨立演化,互相不受影響。
- 資料隱藏,領域層的某些資料需要對錶示層隱藏(比如使用者密碼),在定義DTO時,可以不設定隱藏欄位的對映,實現資料隱藏。DTO只返回表示層需要的資料,不多也不少。
- 避免序列化問題。領域物件中會帶有迴圈引用,比如詩人Poet會引用詩Poems,而詩Poem中又引用了詩人Poet,這種迴圈引用在序列化時會出現問題。
ABP vNext中DTO和實體的對應關係
ABP vNext使用對映Profile定義DTO和實體之間的對映關係,這與以前版本使用AutoMap標籤是不同的,對映檔案如下:
以前使用如下:
[AutoMapFrom(typeof(Products))]
public class ProductDto:EntityDto
{
public string ProductName { get; set; }
public string ProductImage { get; set; }
public double Price { get; set; }
public double OrgPrice { get; set; }
public string Decoration { get; set; }
public string Sizes { get; set; }
public int ClickTimes { get; set; }
public int SaleTimes { get; set; }
public string DetailText { get; set; }
}
現在使用如下:
using AutoMapper;
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.Application.Poems
{
public class PoemAppAutoMapperProfile : Profile
{
public PoemAppAutoMapperProfile()
{
CreateMap<Poet, PoetDto>();
CreateMap<Core.Poems.Poem, PoemDto>();
CreateMap<Category, CategoryDto>();
CreateMap<CategoryPoem, CategoryPoemDto>();
}
}
}
我們已經建立了領域層,並且使用EF實現了對資料庫的訪問,我們還建立了用於資料交換的DTO,現在繼續應用層的開發。我們需要實現如下基本需求:
- 詩人查詢:按姓名進行模糊查詢
- 根據id獲取詩人資料。
- 詩查詢:
按詩人進行查詢;按關鍵字在標題進行模糊查詢;按分類進行查詢,如果分類是多個,就查詢屬於所有分類的詩。比如,如果查詢條件是“唐詩三百首”和“五言詩”,那麼結果應該是唐詩三百首中的五言詩。 - 根據id獲取詩資料。
- 分類列表:列出所有分類。
- 分類的增、刪:可以增加和刪除分類。
- 查詢某一首詩的所有分類。
上面的功能能夠基本完成詩和詩人查詢分類的功能。
上述功能的定義在介面IPoemAppService中定義,在PoemAppService中實現。IPoemAppService程式碼如下:
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace ZL.AbpNext.Poem.Application.Poems
{
public interface IPoemAppService:IApplicationService
{
/// <summary>
/// 獲取詩人分頁
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
PagedResultDto<PoetDto> GetPagedPoets(PagedResultRequestDto dto);
/// <summary>
/// 查詢詩人,按名字模糊查詢
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
PagedResultDto<PoetDto> SearchPoets(SearchPoetDto dto);
/// <summary>
/// 獲取詩的分頁查詢
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
PagedResultDto<PoemDto> GetPagedPoems(PagedResultRequestDto dto);
/// <summary>
/// 按條件查詢詩,條件是關鍵字(模糊查詢),作者(精確查詢),分類(屬於所有分類)
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
PagedResultDto<PoemDto> SearchPoems(SearchPoemDto dto);
/// <summary>
/// 增加分類,如果已經存在,不增加,返回-1,如果增加成功,返回新增記錄的id
/// </summary>
/// <param name="category"></param>
/// <returns></returns>
CategoryDto AddCategory(CategoryDto category);
/// <summary>
/// 刪除分類
/// </summary>
/// <param name="category"></param>
void DeleteCategory(CategoryDto category);
/// <summary>
/// 分類列表
/// </summary>
/// <returns></returns>
List<CategoryDto> GetAllCategories();
/// <summary>
/// 將詩關聯到分類
/// </summary>
/// <param name="categoryPoem"></param>
void AddPoemToCategory(CategoryPoemDto categoryPoem);
/// <summary>
/// 解除詩和分類的關聯
/// </summary>
/// <param name="categoryPoem"></param>
void RemovePoemFromCategory(CategoryPoemDto categoryPoem);
List<CategoryPoemDto> GetCategoryPoems();
/// <summary>
/// 列出詩的分類
/// </summary>
/// <param name="poemid"></param>
/// <returns></returns>
List<CategoryDto> GetPoemCategories(int poemid);
/// <summary>
/// 列出分類的詩
/// </summary>
/// <param name="categoryid"></param>
/// <returns></returns>
List<PoemDto> GetPoemsOfCategory(int categoryid);
PoetDto AddPoet(PoetDto poet);
}
}
現在我們可以編寫PoemAppService,這個類的定義如下:
public class PoemAppService : ApplicationService, IPoemAppService
{
private readonly IRepository<Core.Poems.Poem> _poemRepository;
private readonly IRepository<Category> _categoryRepository;
private readonly IRepository<Poet> _poetRepository;
private readonly IRepository<CategoryPoem> _categoryPoemRepository;
public PoemAppService(IRepository<Core.Poems.Poem> poemRepository
, IRepository<Category> categoryRepository
, IRepository<Poet> poetRepository
, IRepository<CategoryPoem> categoryPoemRepository)
{
_poemRepository = poemRepository;
_categoryRepository = categoryRepository;
_poetRepository = poetRepository;
_categoryPoemRepository = categoryPoemRepository;
}
這裡我們使用Abp提供的通用的IRepository,編寫一般的方法可以滿足需求,比如增加,刪除等等:
public CategoryDto AddCategory(CategoryDto category)
{
var cate = _categoryRepository.FirstOrDefault(o => o.CategoryName == category.CategoryName);
if (cate == null)
{
cate= _categoryRepository.InsertAsync(new Category { CategoryName = category.CategoryName },true).Result;
}
return ObjectMapper.Map<Category,CategoryDto>(cate);
}
public List<CategoryDto> GetAllCategories()
{
return ObjectMapper.Map<List<Category>, List<CategoryDto>>(_categoryRepository.ToList());
}
public void DeleteCategory(CategoryDto category)
{
var cat = _categoryRepository.FirstOrDefault(o => o.Id == category.Id);
if (cat != null)
{
_categoryRepository.DeleteAsync(cat, true);
}
}
這裡需要說明的是,Abp 將ApplicationService中的方法作為工作單元處理,所以不需要像在一開始控制檯應用中那樣顯示使用UnitWork。
當我們進行稍微複雜一些的開發時,發現通用的IRepository不夠用了,比如,如果獲取是的分類,需要寫成這樣:
public List<CategoryDto> GetPoemCategories(int poemid)
{
var lst = _categoryPoemRepository.Where(p => p.PoemId == poemid);
var categories = new List<Category>();
foreach (var cp in lst)
{
var cate = _categoryRepository.GetAsync(o => o.Id == cp.CategoryId).Result;
categories.Add(cate);
}
return ObjectMapper.Map<List<Category>, List<CategoryDto>>(categories);
}
對於更復雜的一些功能,比如模糊查詢,使用預設的IRepository甚至無法實現。下節我們開發定製的Repository。
相關文章
- (精華)2020年8月22日 ABP vNext 領域層和資料訪問層的單元測試
- [Abp vNext 原始碼分析] - 6. DDD 的應用層支援 (應用服務)原始碼
- (精華2020年5月22日更新) react基礎篇 元件的使用React元件
- ABP VNext學習日記8
- ABP VNext學習日記7
- 控制檯程式使用ABP框架應用層服務框架
- Abp vNext 基礎篇丨分層架構架構
- (精華)2020年7月17日 vue mixins的使用Vue
- (精華)2020年8月2日 TypeScript 裝飾器的使用TypeScript
- (精華)2020年7月22日 ASP.NET Core Swagger的使用(NSwag工具版)ASP.NETSwagger
- (精華)2020年9月2日 .NET Core 命令列的基本使用命令列
- 初識ABP vNext(8):ABP特徵管理特徵
- (精華)2020年7月10日 Node.js express(router路由的使用)Node.jsExpress路由
- 初識ABP vNext(10):ABP設定管理
- Abp vNext 依賴注入依賴注入
- 基於 abp vNext 微服務開發的敏捷應用構建平臺 - 框架分析微服務敏捷框架
- (精華)2020年7月20日 ASP.NET Core serilog日誌框架的使用ASP.NET框架
- (精華)2020年7月20日 ASP.NET Core log4.net日誌框架的使用ASP.NET框架
- (精華2020年5月17日更新) vue實戰篇 手寫vue底層原始碼Vue原始碼
- (精華2020年5月8日更新) vue教程篇 vue-router路由的使用Vue路由
- 初識ABP vNext(5):ABP擴充套件實體套件
- (精華)2020年6月28日 Canvas 進度條Canvas
- (精華)2020年8月18日 快取機制快取
- Windbg在應用層除錯漏洞時的應用除錯
- ABP vNext 審計日誌獲取真實客戶端IP客戶端
- 初識ABP vNext(3):vue對接ABP基本思路Vue
- 淺談Abp vNext的模組化設計
- Abp Vnext Vue3 的版本實現Vue
- Abp vNext 模組載入機制
- 原始碼解析-Abp vNext丨LocalEventBus原始碼
- 分析Tapestry用例!域物件作為DTO在各層傳輸(狀態控制)物件
- (精華)2020年6月28日 Canvas 基礎知識Canvas
- (精華)2020年7月18日 vue clipboard複製剪下Vue
- (精華)2020年7月1日 ASP.NET Core Swagger的使用(Swashbuckle工具版)ASP.NETSwagger
- (精華2020年5月4日更新) vue教程篇 計算屬性computed的使用Vue
- (精華2020年5月4日更新) vue教程篇 v-show和v-if的使用Vue
- 初識ABP vNext(6):vue+ABP實現國際化Vue
- 初識ABP vNext(9):ABP模組化開發-檔案管理