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);

        }

    }

}
相關文章
相關標籤/搜索