ABP學習入門系列(四)(創建Service)

来源:http://www.cnblogs.com/tianjiaxiaobaicai/archive/2017/11/14/7833601.html
-Advertisement-
Play Games

一,一些相關解釋 Service 在應用服務層也就是application層。應用服務用於將領域(業務)邏輯暴露給展現層。展現層通過傳入DTO(數據傳輸對象)參數來調用應用服務,而應用服務通過領域對象來執行相應的業務邏輯並且將DTO返回給展現層。 也就是這樣避免了應用服務層和展現層的,直接數據交互, ...


一,一些相關解釋

Service 在應用服務層也就是application層。應用服務用於將領域(業務)邏輯暴露給展現層。展現層通過傳入DTO(數據傳輸對象)參數來調用應用服務,而應用服務通過領域對象來執行相應的業務邏輯並且將DTO返回給展現層。

也就是這樣避免了應用服務層和展現層的,直接數據交互,而是通過dto實現了數據過濾,這樣就可以較好的避免非法數據的傳入傳出。另外大頭還要實現數據隱藏,方便擴展等好處。

創建應用服務時需要註意:

1.service 要實現IApplicationService介面。

2,ABP為IApplicationService提供預設實現ApplicationService

3,ABP中,一個應用服務方法預設是一個工作單元(Unit of Work)。ABP針對UOW模式自動進行資料庫的連接及事務管理,且會自動保存數據修改。

二,XXService和IXXService

1,如下TaskAppService 繼承了LearningMpaAbpAppServiceBase,並實現了ITaskAppService介面

using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Events.Bus;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Net.Mail.Smtp;
using Abp.Notifications;
using Abp.Runtime.Session;
using AutoMapper;
using LearningMpaAbp.Authorization;
using LearningMpaAbp.Authorization.Users;
using LearningMpaAbp.Tasks.Dtos;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace LearningMpaAbp.Tasks
{
    /// <summary>
    ///     Implements <see cref="ITaskAppService" /> to perform task related application functionality.
    ///     Inherits from <see cref="ApplicationService" />.
    ///     <see cref="ApplicationService" /> contains some basic functionality common for application services (such as
    ///     logging and localization).
    /// </summary>
    public class TaskAppService : LearningMpaAbpAppServiceBase, ITaskAppService
    {
        private readonly INotificationPublisher _notificationPublisher;
        private readonly ISmtpEmailSender _smtpEmailSender;
        //These members set in constructor using constructor injection.

        private readonly IRepository<Task> _taskRepository;
        private readonly IRepository<User, long> _userRepository;
        private readonly ITaskManager _taskManager;
        private readonly ITaskCache _taskCache;
        private readonly IEventBus _eventBus;

        /// <summary>
        ///     In constructor, we can get needed classes/interfaces.
        ///     They are sent here by dependency injection system automatically.
        /// </summary>
        public TaskAppService(
            IRepository<Task> taskRepository,
            IRepository<User, long> userRepository,
            ISmtpEmailSender smtpEmailSender,
            INotificationPublisher notificationPublisher,
            ITaskCache taskCache,
            ITaskManager taskManager,
            IEventBus eventBus)
        {
            _taskRepository = taskRepository;
            _userRepository = userRepository;
            _smtpEmailSender = smtpEmailSender;
            _notificationPublisher = notificationPublisher;
            _taskCache = taskCache;
            _taskManager = taskManager;
            _eventBus = eventBus;
        }

        public TaskCacheItem GetTaskFromCacheById(int taskId)
        {
            return _taskCache[taskId];
        }

        public IList<TaskDto> GetAllTasks()
        {
            var tasks = _taskRepository.GetAll().OrderByDescending(t => t.CreationTime).ToList();
            return Mapper.Map<IList<TaskDto>>(tasks);
        }

        public GetTasksOutput GetTasks(GetTasksInput input)
        {
            var query = _taskRepository.GetAllIncluding(t => t.AssignedPerson)
                .WhereIf(input.State.HasValue, t => t.State == input.State.Value)
                .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Title.Contains(input.Filter))
                .WhereIf(input.AssignedPersonId.HasValue, t => t.AssignedPersonId == input.AssignedPersonId.Value);

            //排序
            if (!string.IsNullOrEmpty(input.Sorting))
                query = query.OrderBy(input.Sorting);
            else
                query = query.OrderByDescending(t => t.CreationTime);

            var taskList = query.ToList();

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return new GetTasksOutput
            {
                Tasks = Mapper.Map<List<TaskDto>>(taskList)
            };
        }


        public PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input)
        {
            //初步過濾
            var query = _taskRepository.GetAllIncluding(t => t.AssignedPerson)
                .WhereIf(input.State.HasValue, t => t.State == input.State.Value)
                .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Title.Contains(input.Filter))
                .WhereIf(input.AssignedPersonId.HasValue, t => t.AssignedPersonId == input.AssignedPersonId.Value);

            //排序
            query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(input.Sorting) : query.OrderByDescending(t => t.CreationTime);

            //獲取總數
            var tasksCount = query.Count();
            //預設的分頁方式
            //var taskList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            //ABP提供了擴展方法PageBy分頁方式
            var taskList = query.PageBy(input).ToList();

            return new PagedResultDto<TaskDto>(tasksCount, taskList.MapTo<List<TaskDto>>());
        }

        public async Task<TaskDto> GetTaskByIdAsync(int taskId)
        {
            //Called specific GetAllWithPeople method of task repository.
            var task = await _taskRepository.GetAsync(taskId);

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return task.MapTo<TaskDto>();
        }

        public TaskDto GetTaskById(int taskId)
        {
            var task = _taskRepository.Get(taskId);

            return task.MapTo<TaskDto>();
        }

        public void UpdateTask(UpdateTaskInput input)
        {
            //We can use Logger, it's defined in ApplicationService base class.
            Logger.Info("Updating a task for input: " + input);

            //獲取是否有許可權
            bool canAssignTaskToOther = PermissionChecker.IsGranted(PermissionNames.Pages_Tasks_AssignPerson);
            //如果任務已經分配且未分配給自己,且不具有分配任務許可權,則拋出異常
            if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != AbpSession.GetUserId() &&
                !canAssignTaskToOther)
            {
                throw new AbpAuthorizationException("沒有分配任務給他人的許可權!");
            }

            var updateTask = Mapper.Map<Task>(input);
            var user = _userRepository.Get(input.AssignedPersonId.Value);
            //先執行分配任務
            _taskManager.AssignTaskToPerson(updateTask, user);

            //再更新其他欄位
            _taskRepository.Update(updateTask);

        }

        public void AssignTaskToPerson(AssignTaskToPersonInput input)
        {
            var task = _taskRepository.Get(input.TaskId);
            var user = _userRepository.Get(input.UserId);
            _taskManager.AssignTaskToPerson(task, user);
            //這裡有一個問題就是,當開發人員不知道有這個TaskManager時,依然可以通過直接修改Task的AssignedPersonId屬性就行任務分配。

            //分配任務成功後,觸發領域事件,發送郵件通知
            //_eventBus.Trigger(new TaskAssignedEventData(task, user));//由領域服務觸發領域事件

        }

        public int CreateTask(CreateTaskInput input)
        {
            //We can use Logger, it's defined in ApplicationService class.
            Logger.Info("Creating a task for input: " + input);

            //判斷用戶是否有許可權
            if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != AbpSession.GetUserId())
                PermissionChecker.Authorize(PermissionNames.Pages_Tasks_AssignPerson);

            var task = Mapper.Map<Task>(input);

            int result = _taskRepository.InsertAndGetId(task);

            //只有創建成功才發送郵件和通知
            if (result > 0)
            {
                if (input.AssignedPersonId.HasValue)
                {
                    var user = _userRepository.Load(input.AssignedPersonId.Value);
                    //task.AssignedPerson = user;
                    //var message = "You hava been assigned one task into your todo list.";

                    //使用領域事件觸發發送通知操作
                    _eventBus.Trigger(new TaskAssignedEventData(task, user));

                    //TODO:需要重新配置QQ郵箱密碼
                    //_smtpEmailSender.Send("[email protected]", task.AssignedPerson.EmailAddress, "New Todo item", message);

                    //_notificationPublisher.Publish("NewTask", new MessageNotificationData(message), null,
                    //    NotificationSeverity.Info, new[] { task.AssignedPerson.ToUserIdentifier() });
                }
            }

            return result;
        }

       
        public void Delete(int id)
        {
            var task = _taskRepository.Get(id);
            if (task != null)
                _taskRepository.Delete(task);
        }
    }
}

2,ITaskAppService 繼承IApplicationService

using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Linq.Extensions;
using LearningMpaAbp.Tasks.Dtos;

namespace LearningMpaAbp.Tasks
{
    public interface ITaskAppService : IApplicationService
    {
        GetTasksOutput GetTasks(GetTasksInput input);

        PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input);

        void UpdateTask(UpdateTaskInput input);

        int CreateTask(CreateTaskInput input);

        Task<TaskDto> GetTaskByIdAsync(int taskId);

        TaskDto GetTaskById(int taskId);

        void Delete(int taskId);

        TaskCacheItem GetTaskFromCacheById(int taskId);

        IList<TaskDto> GetAllTasks();
    }
}

 

三,Dto 數據傳輸對象(Data Transfer Objects)用於應用層和展現層的數據傳輸

ABP 建議命名 input/ouput 對象類似於 MethodNameInput/MethodNameOutput,對於每個應用服務方法都需要將 Input Output 進行分開定義。甚至你的方法只接
收或者返回一個值,也最好創建相應的 DTO 類型。 這樣會使代碼有更好的擴展性

using System.Collections.Generic;

namespace LearningMpaAbp.Tasks.Dtos
{
    public class GetTasksOutput
    {
        public List<TaskDto> Tasks { get; set; }
    }
}

 有一個問題怎麼將task實體類轉換為dto,這時就需要進行映射了AutoMapper 根據 Task實體創建了 taskDto,並根據命名約定來給
PersonDto 的屬性賦值 。

 

以上。。

參考:http://www.jianshu.com/p/da69ca7b27c6

代碼:https://github.com/tianxiangd/LearnAbp

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MongDB .Net工具庫MongoRepository的簡單使用 最近研究了一下MongoDB資料庫,並使用了開源的在.net環境下的一個類庫,Mongo倉庫。對於數據的一些簡單的操作非常好用,特記錄供後期參考。 具體的使用過程如下: 一、新建項目,在Nuget上獲取庫。 二、在配置文件中設置數 ...
  • HAL(Hypertext Application Language,超文本應用語言)是一種RESTful API的數據格式風格,為RESTful API的設計提供了介面規範,同時也降低了客戶端與服務端介面的耦合度。很多當今流行的RESTful API開發框架,包括Spring REST,也都預設支 ...
  • 1.1 概述 c#程式開發中,資料庫操作無疑是舉足輕重的,資料庫部分的技術點可能占整個c#技術點的1/4。這幾天我一直在研究System.Data.OracleClient.dll反編譯之後的.CS,放棄c#的心都有了,底層代碼不僅全是英文註釋,而且有很多東西看都看不懂,讓我深刻體會封裝的重要性!此 ...
  • 今天是第一次接觸C#,由於長時間的做Java開發,突然轉到C#非常的不自然,但是也有了一些收穫,給大家分享一下 ...
  • "sweetalert": "^1.1.3",記住這個參數,Abp中這個組件只能用這個版本,高於它的message會沒有效果,切記 ...
  • 回到目錄 進行dotnetcore之後,各種對象都是基於DI進行生產的,這就有了對象的生命周期一說,早在autofac里也有相關知識點,這與Microsoft.Extensions.DependencyInjection是完全溫和的,方便大家理解,在講今天的組件化之前,先對DI的三種生命周期進行理解 ...
  • 大致要實現的 效果如下 1,添加Controller(用到的X.PagedList 註意到nuget添加) 2,視圖 另外還有_createTaskPartial,_EditTaskPartial 等,這裡就不貼代碼了 以上。。。 參考http://www.jianshu.com/p/620c20f ...
  • 最近在練習EF的過程中,實現將Linq返回的結果綁定到Combox時出錯。 錯誤提示如下: System.NotSupportedException:“Data binding directly to a store query (DbSet, DbQuery, DbSqlQuery, DbRawS... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...