(精华)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; }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
现在使用如下:
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>();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
我们已经创建了领域层,并且使用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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
现在我们可以编写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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
这里我们使用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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
这里需要说明的是,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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
对于更复杂的一些功能,比如模糊查询,使用缺省的IRepository甚至无法实现。下节我们开发定制的Repository。
文章来源: codeboy.blog.csdn.net,作者:愚公搬代码,版权归原作者所有,如需转载,请联系作者。
原文链接:codeboy.blog.csdn.net/article/details/108169742
- 点赞
- 收藏
- 关注作者
评论(0)