zoukankan      html  css  js  c++  java
  • abp(net core)+easyui+efcore实现仓储管理系统——创建应用服务(五)

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

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

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

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

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

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

    一、解释下应用服务层

         应用服务用于将领域(业务)逻辑暴露给展现层。展现层通过传入DTO(数据传输对象)参数来调用应用服务,而应用服务通过领域对象来执行相应的业务逻辑并且将DTO返回给展现层。因此,展现层和领域层将被完全隔离开来。
    以下几点,在创建应用服务时需要注意:

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

    二、定义应用服务接口需要用到的DTO

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

        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都要自己手动去转换成对应实体,这个工作量也是不可小觑啊。
    聪明如你,你肯定会想肯定有什么方法来减少这个工作量。

    三、使用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>
        {
    
          ...
    
        }

     

    四、定义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)进行数据传输。

    五、实现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);
    
            }
    
        }
    
    }
  • 相关阅读:
    Select For Update使用场景   
    数据库的ACID特性
    Zookeeper和Eureka的区别
    SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决?
    如果你也用过struts2.简单介绍下springMVC和struts2的区别有哪些?
    如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?
    延迟加载与session关闭的矛盾一般可以这样处理:
    举一个多对多关联的例子,并说明如何实现多对多关联映射。
    java的基本操作和基本知识技能
    HTML基础
  • 原文地址:https://www.cnblogs.com/chillsrc/p/11065667.html
Copyright © 2011-2022 走看看