abp(net core)+easyui+efcore实现仓储管理系统——建立应用服务(五)

abp(net core)+easyui+efcore实现仓储管理系统目录

abp(net core)+easyui+efcore实现仓储管理系统——ABP整体介绍(一)html

abp(net core)+easyui+efcore实现仓储管理系统——解决方案介绍(二)数据库

abp(net core)+easyui+efcore实现仓储管理系统——领域层建立实体(三)app

 abp(net core)+easyui+efcore实现仓储管理系统——定义仓储并实现 (四)async

 

      在上一篇文章中学习了ABP的仓储(Repository)功能,Repository对数据库进行增删改查操做。在这一篇文章中咱们主要了解应用服务层。post

1、解释下应用服务层学习

     应用服务用于将领域(业务)逻辑暴露给展示层。展示层经过传入DTO(数据传输对象)参数来调用应用服务,而应用服务经过领域对象来执行相应的业务逻辑而且将DTO返回给展示层。所以,展示层和领域层将被彻底隔离开来。
如下几点,在建立应用服务时须要注意:ui

  1. 在ABP中,一个应用服务须要实现IApplicationService接口,最好的实践是针对每一个应用服务都建立相应继承自IApplicationService的接口。(经过继承该接口,ABP会自动帮助依赖注入)
  2. ABP为IApplicationService提供了默认的实现ApplicationService,该基类提供了方便的日志记录和本地化功能。实现应用服务的时候继承自ApplicationService并实现定义的接口便可。
  3. ABP中,一个应用服务方法默认是一个工做单元(Unit of Work)。ABP针对UOW模式自动进行数据库的链接及事务管理,且会自动保存数据修改。

2、定义应用服务接口须要用到的DTOspa

    1. 在Visual Studio 2017的“解决方案资源管理器”中,右键单击“ABP.TPLMS.Application”项目。 选择“添加” > “新建文件夹”。3d

    2.将文件夹命名为“Modules”。日志

    3. 右键单击“Modules”文件夹,选择“添加” > “新建文件夹”。将文件夹重命名为“Dto”。以下图。

 

      4. 右键单击“Dto”文件夹,而后选择“添加” > “类”。 将类命名为 ModuleDto,而后选择“添加”。代码以下。

using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using ABP.TPLMS.Entitys;
using System;
using System.Collections.Generic;
using System.Text;
namespace ABP.TPLMS.Modules.Dto
{
    [AutoMapFrom(typeof(Module))]
    public class ModuleDto:EntityDto<long>
    {
        public string DisplayName { get; set; }
        public string Name { get; set; }      

        public string Url { get; set; }       
        public string HotKey { get; set; }
        public int ParentId { get; set; }
        public bool RequiresAuthentication { get; set; }
        public bool IsAutoExpand { get; set; }       
        public string IconName { get; set; }
        public int Status { get; set; }
        public string ParentName { get; set; }    

        public string RequiredPermissionName { get; set; }
        public int SortNo { get; set; }   
    }
}
  • 为了在页面上展现模块信息,ModuleDto被用来将模块数据传递到基础设施层。
  • ModuleDto继承自 EntityDto<long>.跟在领域层定义的Module类同样具备一些相同属性。
  • [AutoMapFrom(typeof(Module))]用来建立从Module类到ModuleDto的映射.使用这种方法。你能够将Module对象自动转换成ModuleDto对象(而不是手动复制全部的属性)。

      5. 右键单击“Dto”文件夹,而后选择“添加” > “类”。 将类命名为 CreateUpdateModuleDto ,而后选择“添加”。代码以下。

using Abp.Application.Services.Dto;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text; 

namespace ABP.TPLMS.Modules.Dto
{
   public  class CreateUpdateModuleDto : EntityDto<long>
    {

        public const int MaxLength = 255;

        [Required]
        [StringLength(MaxLength)]
        public string DisplayName { get; set; }

        [Required]
        [StringLength(MaxLength)]
        public string Name { get; set; }

        [Required]
        [StringLength(MaxLength)]
        public string Url { get; set; }

        [StringLength(MaxLength)]
        public string HotKey { get; set; }
        public int ParentId { get; set; }
        public bool RequiresAuthentication { get; set; }

        public bool IsAutoExpand { get; set; }

        [StringLength(MaxLength)]
        public string IconName { get; set; }

        public int Status { get; set; }

        [Required]
        [StringLength(MaxLength)]
        public string ParentName { get; set; }

        [StringLength(MaxLength)]
        public string RequiredPermissionName { get; set; }
        public int SortNo { get; set; }    
    }
}
  • 这个DTO类在建立和更新模块信息的时候被使用,用来从页面获取模块信息。
  • 类中的属性定义了数据注解(如[Required])用来定义有效性验证。ABP会自动校验DTO的数据有效性。

  6. 为何须要经过dto进行数据传输?

     通常来讲,使用DTO进行数据传输具备如下好处。

  • 数据隐藏
  • 序列化和延迟加载问题
  • ABP对DTO提供了约定类以支持验证
  • 参数或返回值改变,经过Dto方便扩展
  • DTO类被用来在 基础设施层 和 应用层 传递数据.

  7.Dto规范 (灵活应用)

  • ABP建议命名输入/输出参数为:MethodNameInput和MethodNameOutput
  • 并为每一个应用服务方法定义单独的输入和输出DTO(若是为每一个方法的输入输出都定义一个dto,那将有一个庞大的dto类须要定义维护。通常经过定义一个公用的dto进行共用)
  • 即便你的方法只接受/返回一个参数,也最好是建立一个DTO类
  • 通常会在对应实体的应用服务文件夹下新建Dtos文件夹来管理Dto类。

      定义完DTO,是否是脑壳有个疑问,我在用DTO在展示层与应用服务层进行数据传输,但最终这些DTO都须要转换为实体才能与数据库直接打交道啊。若是每一个dto都要本身手动去转换成对应实体,这个工做量也是不可小觑啊。
聪明如你,你确定会想确定有什么方法来减小这个工做量。

3、使用AutoMapper自动映射DTO与实体

    1.简要介绍AutoMapper

    开始以前,若是对AutoMapper不是很了解,建议看下这篇文章AutoMapper小结

     AutoMapper的使用步骤,简单总结下:

  • 建立映射规则(Mapper.CreateMap<source, destination>();)
  • 类型映射转换(Mapper.Map<source,destination>(sourceModel))

     在Abp中有两种方式建立映射规则:

  • 特性数据注解方式:
    • AutoMapFrom、AutoMapTo 特性建立单向映射
    • AutoMap 特性建立双向映射
  • 代码建立映射规则:
    • Mapper.CreateMap<source, destination>();

     2.为Module实体相关的Dto定义映射规则

      ModuleDto、CreateUpdateModuleDto中的属性名与Module实体的属性命名一致,且只须要从Dto映射到实体,不须要反向映射。因此经过AutoMapTo建立单向映射便可。

  [AutoMapTo(typeof(Module))] //定义单向映射
    public class ModuleDto:EntityDto<long>
{

      ...

}

     [AutoMapTo(typeof(Module))] //定义单向映射
    public  class CreateUpdateModuleDto : EntityDto<long>
    {

      ...

    }

 

4、定义IModuleAppService接口

   1. 右键单击“Dto”文件夹,而后选择“添加” > “新建项”,在弹出对话框中选择“接口”。为应用服务定义一个名为 IModuleAppService 的接口。代码以下。

 using Abp.Application.Services;
using Abp.Application.Services.Dto;
using ABP.TPLMS.Modules.Dto;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks; 

namespace ABP.TPLMS.Modules
{

    public interface IModuleAppService : IApplicationService
    {

        Task CreateAsync(CreateUpdateModuleDto input);
        Task UpdateAsync(CreateUpdateModuleDto input);
        Task<ListResultDto<ModuleDto>> GetAllAsync();
        Task  DeleteAsync(int Id);
        void Delete(int Id);
    }
}

      从上面的代码中咱们仔细看一下方法的参数及返回值,你们可能会发现并未直接使用Module实体对象。这是为何呢?由于展示层与应用服务层是经过Data Transfer Object(DTO)进行数据传输。

5、实现IModuleAppService

     对于具体的业务来说,只是简单的增删该查,实现起来就很简单了。代码以下:

using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using ABP.TPLMS.Entitys;
using ABP.TPLMS.Modules.Dto;
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks; 

namespace ABP.TPLMS.Modules
{
    public class ModuleAppService : ApplicationService, IModuleAppService
{

        private readonly IRepository<Module> _moduleRepository;

        public ModuleAppService(IRepository<Module> moduleRepository)
        {

            _moduleRepository = moduleRepository;
        }

        public Task CreateAsync(CreateUpdateModuleDto input)
        {
            var module =  Mapper.Map<Module>(input);
            return _moduleRepository.InsertAsync(module);
        }

        public Task UpdateAsync(CreateUpdateModuleDto input)
        {           
           var module = Mapper.Map<Module>(input);
            return _moduleRepository.UpdateAsync(module);
        }

        public async Task<ListResultDto<ModuleDto>> GetAllAsync()
        {
            var books = await _moduleRepository.GetAllListAsync();

            return new ListResultDto<ModuleDto>(ObjectMapper.Map<List<ModuleDto>>(books));          

        }

       public async Task DeleteAsync(int Id)
        {
             await _moduleRepository.DeleteAsync(Id);         

        }

        public  void Delete(int Id)
        {
             _moduleRepository.Delete(Id);

        }

    }

}
相关文章
相关标签/搜索