(精华)2020年8月22日 ABP vNext DTO在应用层的使用

举报
愚公搬代码 发表于 2021/10/19 23:28:53 2021/10/19
【摘要】 我们继续应用层的开发,首先创建负责在应用层和展示层之间传递数据的对象,也就是DTO。 使用DTO的原因 为什么需要DTO呢?有如下几个原因。 隔离领域层与表示层,使领域层和表示层可以独立演化,互相不...

我们继续应用层的开发,首先创建负责在应用层和展示层之间传递数据的对象,也就是DTO。

使用DTO的原因

为什么需要DTO呢?有如下几个原因。

  1. 隔离领域层与表示层,使领域层和表示层可以独立演化,互相不受影响。
  2. 数据隐藏,领域层的某些数据需要对表示层隐藏(比如用户密码),在定义DTO时,可以不设置隐藏字段的映射,实现数据隐藏。DTO只返回表示层需要的数据,不多也不少。
  3. 避免序列化问题。领域对象中会带有循环引用,比如诗人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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。