ASP.NET Core搭建多層網站架構【8.3-編寫角色業務的增刪改】

2020/01/29, ASP.NET Core 3.1, VS2019html

摘要:基於ASP.NET Core 3.1 WebApi搭建後端多層網站架構【8.3-編寫角色業務的增刪改】
編寫最簡單的增刪改業務,涉及到DI依賴注入的使用、AutoMapper的使用、工做單元與倉儲的使用、雪花Id的生成git

文章目錄github

此分支項目代碼web

本章節介紹了編寫最簡單的增刪改查業務,涉及到DI依賴注入的使用、AutoMapper的使用、工做單元與倉儲的使用sql

類庫添加引用

MS.Services類庫添加對MS.Models項目的引用數據庫

BaseService

MS.Services類庫中添加BaseService.cs類:後端

using AutoMapper;
using MS.Common.IDCode;
using MS.DbContexts;
using MS.UnitOfWork;

namespace MS.Services
{
    public interface IBaseService
    {
    }
    public class BaseService : IBaseService
    {
        public readonly IUnitOfWork<MSDbContext> _unitOfWork;
        public readonly IMapper _mapper;
        public readonly IdWorker _idWorker;

        public BaseService(IUnitOfWork<MSDbContext> unitOfWork, IMapper mapper, IdWorker idWorker)
        {
            _unitOfWork = unitOfWork;
            _mapper = mapper;
            _idWorker = idWorker;
        }
    }
}

說明:api

  • 新建了IBaseService接口,後面新建的服務接口都要繼承自該接口
  • 新建了BaseService類,實現了IBaseService接口
  • 能夠看到BaseService類中,使用構造函數的方式依賴注入獲得了IUnitOfWork _unitOfWork、IMapper _mapper、IdWorker _idWorker,而且是public類型,因此繼承BaseService的類均可以直接使用父類的這三個成員

RoleService

MS.Services類庫中新建Role文件夾,在該文件夾下新建IRoleService.csRoleService.cs類,注意我這裏兩個類的命名空間都改成namespace MS.Services,而不是默認的namespace MS.Services.Role緩存

IRoleService接口

修改IRoleService爲public類型的interface接口,繼承自IBaseService,並添加Create、Update、Delete三個方法:架構

using MS.Entities;
using MS.Models.ViewModel;
using MS.WebCore.Core;
using System.Threading.Tasks;

namespace MS.Services
{
    public interface IRoleService : IBaseService
    {
        Task<ExecuteResult<Role>> Create(RoleViewModel viewModel);
        Task<ExecuteResult> Update(RoleViewModel viewModel);
        Task<ExecuteResult> Delete(RoleViewModel viewModel);
    }
}

RoleService實現

修改RoleService爲public類型,繼承自BaseService和IRoleService接口,而後使用快速操做生成構造函數和實現接口

接下來開始實現新增Role的業務方法:

public async Task<ExecuteResult<Role>> Create(RoleViewModel viewModel)
{
    ExecuteResult<Role> result = new ExecuteResult<Role>();
    //檢查字段
    if (viewModel.CheckField(ExecuteType.Create, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
    {
        return result.SetFailMessage(checkResult.Message);
    }
    using (var tran = _unitOfWork.BeginTransaction())//開啓一個事務
    {
        Role newRow = _mapper.Map<Role>(viewModel);
        newRow.Id = _idWorker.NextId();//獲取一個雪花Id
        newRow.Creator = 1219490056771866624;//因爲暫時尚未作登陸,因此拿不到登陸者信息,先隨便寫一個後面再完善
        newRow.CreateTime = DateTime.Now;
        _unitOfWork.GetRepository<Role>().Insert(newRow);
        await _unitOfWork.SaveChangesAsync();
        await tran.CommitAsync();//提交事務

        result.SetData(newRow);//添加成功,把新的實體返回回去
    }
    return result;
}

說明:

  • 異步方法要加上async標記
  • 執行添加以前,先進行了字段檢查,若是不經過,則返回錯誤信息
  • 使用了var tran = _unitOfWork.BeginTransaction()開啓了事務,若是遇到異常,會自動回滾,若是不須要使用事務,能夠去除,這裏只是順帶演示下事務的使用方法
  • 使用了_mapper.Map方法把字段從ViewModel映射到實體類中
  • _idWorker.NextId()方法獲取一個雪花Id
  • 因爲尚未作登陸,因此沒有建立者信息,因此先隨便寫了一個,等作了登陸以後再修改
  • 這裏方法內部沒有作trycatch捕獲異常處理,以後會使用AOP攔截器,攔截業務層的每一個方法,統一進行業務異常捕獲處理

WebApi中調用Service

MS.WebApi應用程序中,RoleController.cs類中,添加RoleService接口,並在Post中調用Create方法:

//using MS.Services;
//以上代碼添加到using引用
public class RoleController : ControllerBase
{
    private readonly IRoleService _roleService;

    public RoleController(IRoleService roleService)
    {
        _roleService = roleService;
    }

    [HttpPost]
    public async Task<ExecuteResult> Post(RoleViewModel viewModel)
    {
        return await _roleService.Create(viewModel);
    }
}

說明:

  • 這裏依然使用了構造函數依賴注入獲取一個接口服務
  • 接口設計知足Restful規範

將接口服務添加到依賴注入

MS.WebApi應用程序中,在Startup.cs類的ConfigureServices方法中追加:

//using MS.Services;
//以上代碼添加到using
//註冊IBaseService和IRoleService接口及對應的實現類
services.AddScoped<IBaseService, BaseService>();
services.AddScoped<IRoleService, RoleService>();

測試

完成後啓動項目,打開Postman調試接口:

能夠看到接口調用成功(也能夠看到在控制檯中有EntityFrameworkCore執行的sql語句)
在數據庫中看到新增的記錄:

再重複調用一次接口,則會提示角色名稱已存在:

完整的增刪改角色業務代碼:

using AutoMapper;
using MS.Common.IDCode;
using MS.DbContexts;
using MS.Entities;
using MS.Models.ViewModel;
using MS.UnitOfWork;
using MS.WebCore.Core;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MS.Services
{
    public class RoleService : BaseService, IRoleService
    {
        public RoleService(IUnitOfWork<MSDbContext> unitOfWork, IMapper mapper, IdWorker idWorker) : base(unitOfWork, mapper, idWorker)
        {
        }

        public async Task<ExecuteResult<Role>> Create(RoleViewModel viewModel)
        {
            ExecuteResult<Role> result = new ExecuteResult<Role>();
            //檢查字段
            if (viewModel.CheckField(ExecuteType.Create, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
            {
                return result.SetFailMessage(checkResult.Message);
            }
            using (var tran = _unitOfWork.BeginTransaction())//開啓一個事務
            {
                Role newRow = _mapper.Map<Role>(viewModel);
                newRow.Id = _idWorker.NextId();//獲取一個雪花Id
                newRow.Creator = 1219490056771866624;//因爲暫時尚未作登陸,因此拿不到登陸者信息,先隨便寫一個後面再完善
                newRow.CreateTime = DateTime.Now;
                _unitOfWork.GetRepository<Role>().Insert(newRow);
                await _unitOfWork.SaveChangesAsync();
                await tran.CommitAsync();//提交事務

                result.SetData(newRow);//添加成功,把新的實體返回回去
            }
            return result;
        }

        public async Task<ExecuteResult> Delete(RoleViewModel viewModel)
        {
            ExecuteResult result = new ExecuteResult();
            //檢查字段
            if (viewModel.CheckField(ExecuteType.Delete, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
            {
                return checkResult;
            }
            _unitOfWork.GetRepository<Role>().Delete(viewModel.Id);
            await _unitOfWork.SaveChangesAsync();//提交
            return result;
        }

        public async Task<ExecuteResult> Update(RoleViewModel viewModel)
        {
            ExecuteResult result = new ExecuteResult();
            //檢查字段
            if (viewModel.CheckField(ExecuteType.Update, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
            {
                return checkResult;
            }

            //從數據庫中取出該記錄
            var row = await _unitOfWork.GetRepository<Role>().FindAsync(viewModel.Id);//在viewModel.CheckField中已經獲取了一次用於檢查,因此此處不會重複再從數據庫取一次,有緩存
            //修改對應的值
            row.Name = viewModel.Name;
            row.DisplayName = viewModel.DisplayName;
            row.Remark = viewModel.Remark;
            row.Modifier = 1219490056771866624;//因爲暫時尚未作登陸,因此拿不到登陸者信息,先隨便寫一個後面再完善
            row.ModifyTime = DateTime.Now;
            _unitOfWork.GetRepository<Role>().Update(row);
            await _unitOfWork.SaveChangesAsync();//提交

            return result;
        }
    }
}

完整的接口代碼:

using Microsoft.AspNetCore.Mvc;
using MS.Models.ViewModel;
using MS.Services;
using MS.WebCore.Core;
using System.Threading.Tasks;

namespace MS.WebApi.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class RoleController : ControllerBase
    {
        private readonly IRoleService _roleService;

        public RoleController(IRoleService roleService)
        {
            _roleService = roleService;
        }

        [HttpPost]
        public async Task<ExecuteResult> Post(RoleViewModel viewModel)
        {
            return await _roleService.Create(viewModel);
        }

        [HttpPut]
        public async Task<ExecuteResult> Put(RoleViewModel viewModel)
        {
            return await _roleService.Update(viewModel);
        }

        [HttpDelete]
        public async Task<ExecuteResult> Delete(long id)
        {
            return await _roleService.Delete(new RoleViewModel { Id = id });
        }
    }
}

更新接口測試:

刪除接口測試:

項目完成後,以下圖所示

相關文章
相關標籤/搜索