2020/01/29, ASP.NET Core 3.1, VS2019
摘要:基於ASP.NET Core 3.1 WebApi搭建后端多層網站架構【8.3-編寫角色業務的增刪改】
編寫最簡單的增刪改業務,涉及到DI依賴注入的使用、AutoMapper的使用、工作單元與倉儲的使用、雪花Id的生成
本章節介紹了編寫最簡單的增刪改查業務,涉及到DI依賴注入的使用、AutoMapper的使用、工作單元與倉儲的使用
類庫添加引用
向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;
}
}
}
說明:
- 新建了IBaseService接口,后面新建的服務接口都要繼承自該接口
- 新建了BaseService類,實現了IBaseService接口
- 可以看到BaseService類中,使用構造函數的方式依賴注入得到了IUnitOfWork
_unitOfWork、IMapper _mapper、IdWorker _idWorker,並且是public類型,所以繼承BaseService的類都可以直接使用父類的這三個成員
RoleService
在MS.Services類庫中新建Role文件夾,在該文件夾下新建IRoleService.cs、RoleService.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 });
}
}
}
更新接口測試:

刪除接口測試:

項目完成后,如下圖所示


